1 /***********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 /***********************************************************************
15   Functions for handling the tilespec files which describe
16   the files and contents of tilesets.
17   original author: David Pfitzner <dwp@mso.anu.edu.au>
18 ***********************************************************************/
19 
20 #ifdef HAVE_CONFIG_H
21 #include <fc_config.h>
22 #endif
23 
24 #include <stdio.h>
25 #include <stdlib.h>		/* exit */
26 #include <stdarg.h>
27 #include <string.h>
28 
29 /* utility */
30 #include "astring.h"
31 #include "bitvector.h"
32 #include "capability.h"
33 #include "deprecations.h"
34 #include "fcintl.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "rand.h"
38 #include "registry.h"
39 #include "shared.h"
40 #include "string_vector.h"
41 #include "support.h"
42 
43 /* common */
44 #include "base.h"
45 #include "effects.h"
46 #include "game.h"		/* game.control.styles_count */
47 #include "government.h"
48 #include "map.h"
49 #include "movement.h"
50 #include "nation.h"
51 #include "player.h"
52 #include "road.h"
53 #include "specialist.h"
54 #include "unit.h"
55 #include "unitlist.h"
56 
57 /* client/include */
58 #include "dialogs_g.h"
59 #include "graphics_g.h"
60 #include "gui_main_g.h"
61 #include "mapview_g.h"          /* for update_map_canvas_visible */
62 #include "menu_g.h"
63 #include "themes_g.h"
64 
65 /* client */
66 #include "citydlg_common.h"	/* for generate_citydlg_dimensions() */
67 #include "client_main.h"
68 #include "climap.h"		/* for client_tile_get_known() */
69 #include "colors_common.h"
70 #include "control.h"		/* for fill_xxx */
71 #include "editor.h"
72 #include "goto.h"
73 #include "helpdata.h"
74 #include "options.h"		/* for fill_xxx */
75 #include "themes_common.h"
76 
77 #include "tilespec.h"
78 
79 #define TILESPEC_CAPSTR "+Freeciv-2.6-tilespec duplicates_ok"
80 /*
81  * Tilespec capabilities acceptable to this program:
82  *
83  * +Freeciv-2.6-tilespec
84  *    - basic format for Freeciv versions 2.6.x; required
85  *
86  * +Freeciv-tilespec-Devel-YYYY.MMM.DD
87  *    - tilespec of the development version at the given date
88  *
89  * duplicates_ok
90  *    - we can handle existence of duplicate tags (lattermost tag which
91  *      appears is used; tilesets which have duplicates should specify
92  *      "duplicates_ok")
93  */
94 
95 #define SPEC_CAPSTR "+Freeciv-2.6-spec"
96 /*
97  * Individual spec file capabilities acceptable to this program:
98  *
99  * +Freeciv-2.6-spec
100  *    - basic format for Freeciv versions 2.6.x; required
101  */
102 
103 #define TILESPEC_SUFFIX ".tilespec"
104 #define TILE_SECTION_PREFIX "tile_"
105 
106 /* This the way directional indices are now encoded: */
107 #define MAX_INDEX_CARDINAL 		64
108 #define MAX_INDEX_HALF                  16
109 #define MAX_INDEX_VALID			256
110 
111 #define NUM_TILES_HP_BAR 11
112 #define NUM_TILES_DIGITS 10
113 #define NUM_TILES_SELECT 4
114 #define MAX_NUM_UPKEEP_SPRITES 10
115 
116 #define SPECENUM_NAME extrastyle_id
117 #define SPECENUM_VALUE0 ESTYLE_ROAD_ALL_SEPARATE
118 #define SPECENUM_VALUE0NAME "RoadAllSeparate"
119 #define SPECENUM_VALUE1 ESTYLE_ROAD_PARITY_COMBINED
120 #define SPECENUM_VALUE1NAME "RoadParityCombined"
121 #define SPECENUM_VALUE2 ESTYLE_ROAD_ALL_COMBINED
122 #define SPECENUM_VALUE2NAME "RoadAllCombined"
123 #define SPECENUM_VALUE3 ESTYLE_RIVER
124 #define SPECENUM_VALUE3NAME "River"
125 #define SPECENUM_VALUE4 ESTYLE_SINGLE1
126 #define SPECENUM_VALUE4NAME "Single1"
127 #define SPECENUM_VALUE5 ESTYLE_SINGLE2
128 #define SPECENUM_VALUE5NAME "Single2"
129 #define SPECENUM_VALUE6 ESTYLE_3LAYER
130 #define SPECENUM_VALUE6NAME "3Layer"
131 #define SPECENUM_VALUE7 ESTYLE_CARDINALS
132 #define SPECENUM_VALUE7NAME "Cardinals"
133 #define SPECENUM_COUNT ESTYLE_COUNT
134 #include "specenum_gen.h"
135 
136 /* This could be moved to common/map.h if there's more use for it. */
137 enum direction4 {
138   DIR4_NORTH = 0, DIR4_SOUTH, DIR4_EAST, DIR4_WEST
139 };
140 static const char direction4letters[4] = "udrl";
141 /* This must correspond to enum edge_type. */
142 static const char edge_name[EDGE_COUNT][3] = {"ns", "we", "ud", "lr"};
143 
144 static const int DIR4_TO_DIR8[4] =
145     { DIR8_NORTH, DIR8_SOUTH, DIR8_EAST, DIR8_WEST };
146 
147 enum match_style {
148   MATCH_NONE,
149   MATCH_SAME,		/* "boolean" match */
150   MATCH_PAIR,
151   MATCH_FULL
152 };
153 
154 enum sprite_type {
155   CELL_WHOLE,		/* entire tile */
156   CELL_CORNER		/* corner of tile */
157 };
158 
159 struct drawing_data {
160   bool init;
161 
162   char *name;
163 
164   int num_layers; /* 1 thru MAX_NUM_LAYERS. */
165 #define MAX_NUM_LAYERS 3
166 
167   struct drawing_layer {
168     bool is_tall;
169     int offset_x, offset_y;
170 
171 #define MAX_NUM_MATCH_WITH 8
172     enum match_style match_style;
173     int match_index[1 + MAX_NUM_MATCH_WITH];
174     int match_indices; /* 0 = no match_type, 1 = no match_with */
175 
176     enum sprite_type sprite_type;
177 
178     struct sprite_vector base;
179     struct sprite *match[MAX_INDEX_CARDINAL];
180     struct sprite **cells;
181 
182     /* List of those sprites in 'cells' that are allocated by some other
183      * means than load_sprite() and thus are not freed by unload_all_sprites(). */
184     struct sprite_vector allocated;
185   } layer[MAX_NUM_LAYERS];
186 
187   bool is_reversed;
188 
189   int blending; /* layer, 0 = none */
190   struct sprite *blender;
191   struct sprite *blend[4]; /* indexed by a direction4 */
192 };
193 
194 struct city_style_threshold {
195   struct sprite *sprite;
196 };
197 
198 struct city_sprite {
199   struct {
200     int land_num_thresholds;
201     struct city_style_threshold *land_thresholds;
202   } *styles;
203   int num_styles;
204 };
205 
206 struct river_sprites {
207   struct sprite
208     *spec[MAX_INDEX_CARDINAL],
209     *outlet[MAX_INDEX_CARDINAL];
210 };
211 
212 struct named_sprites {
213   struct sprite
214     *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
215     *treaty_thumb[2],     /* 0=disagree, 1=agree */
216     *arrow[ARROW_LAST], /* 0=right arrow, 1=plus, 2=minus */
217 
218     *icon[ICON_COUNT],
219 
220     *events[E_COUNT],
221 
222     /* The panel sprites for showing tax % allocations. */
223     *tax_luxury, *tax_science, *tax_gold,
224     *dither_tile;     /* only used for isometric view */
225 
226   struct {
227     struct sprite
228       *tile,
229       *worked_tile,
230       *unworked_tile;
231   } mask;
232 
233   struct sprite *tech[A_LAST];
234   struct sprite *building[B_LAST];
235   struct sprite *government[G_LAST];
236 
237   struct {
238     struct sprite *icon[U_LAST];
239     struct sprite *facing[U_LAST][DIR8_MAGIC_MAX];
240     unsigned int default_dir_seed[U_LAST];
241   } units;
242 
243   struct sprite *resource[MAX_NUM_RESOURCES];
244 
245   struct sprite_vector nation_flag;
246   struct sprite_vector nation_shield;
247 
248   struct citizen_graphic {
249     /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
250      * sprites, as defined by the tileset. */
251     int count;
252     struct sprite *sprite[MAX_NUM_CITIZEN_SPRITES];
253   } citizen[CITIZEN_LAST], specialist[SP_MAX];
254   struct sprite *spaceship[SPACESHIP_COUNT];
255   struct {
256     int hot_x, hot_y;
257     struct sprite *frame[NUM_CURSOR_FRAMES];
258   } cursor[CURSOR_LAST];
259   struct {
260     struct sprite_vector unit;
261     struct sprite *nuke;
262   } explode;
263   struct {
264     struct sprite
265       *hp_bar[NUM_TILES_HP_BAR],
266       *vet_lev[MAX_VET_LEVELS],
267       *select[NUM_TILES_SELECT],
268       *auto_attack,
269       *auto_settler,
270       *auto_explore,
271       *fortified,
272       *fortifying,
273       *go_to,			/* goto is a C keyword :-) */
274       *irrigate,
275       *plant,
276       *pillage,
277       *sentry,
278       *stack,
279       *loaded,
280       *transform,
281       *connect,
282       *patrol,
283       *convert,
284       *battlegroup[MAX_NUM_BATTLEGROUPS],
285       *lowfuel,
286       *tired;
287   } unit;
288   struct {
289     struct sprite
290       *unhappy[MAX_NUM_UPKEEP_SPRITES],
291       *output[O_LAST][MAX_NUM_UPKEEP_SPRITES];
292   } upkeep;
293   struct {
294     struct sprite
295       *disorder,
296       *size[NUM_TILES_DIGITS],
297       *size_tens[NUM_TILES_DIGITS],
298       *size_hundreds[NUM_TILES_DIGITS],
299       *tile_foodnum[NUM_TILES_DIGITS],
300       *tile_shieldnum[NUM_TILES_DIGITS],
301       *tile_tradenum[NUM_TILES_DIGITS];
302     struct city_sprite
303       *tile,
304       *single_wall,
305       *wall[NUM_WALL_TYPES],
306       *occupied;
307     struct sprite_vector worked_tile_overlay;
308     struct sprite_vector unworked_tile_overlay;
309   } city;
310   struct citybar_sprites citybar;
311   struct editor_sprites editor;
312   struct {
313     struct {
314       struct sprite *specific;
315       struct sprite *turns[NUM_TILES_DIGITS];
316       struct sprite *turns_tens[NUM_TILES_DIGITS];
317       struct sprite *turns_hundreds[NUM_TILES_DIGITS];
318     } s[GTS_COUNT];
319     struct sprite *waypoint;
320   } path;
321   struct {
322     struct sprite *attention;
323   } user;
324   struct {
325     struct sprite
326       *fog,
327       **fullfog,
328       *darkness[MAX_INDEX_CARDINAL]; /* first unused */
329   } tx;				/* terrain extra */
330   struct {
331     struct sprite
332       *activity,
333       *rmact;
334     enum extrastyle_id extrastyle;
335     union {
336       struct sprite *single;
337       struct sprite *cardinals[MAX_INDEX_CARDINAL];
338       struct {
339         struct sprite
340           *background,
341           *middleground,
342           *foreground;
343       } bmf;
344       struct {
345         struct sprite
346         /* for extrastyles ESTYLE_ROAD_ALL_SEPARATE and ESTYLE_ROAD_PARITY_COMBINED */
347           *isolated,
348           *corner[8]; /* Indexed by direction; only non-cardinal dirs used. */
349         union {
350           /* for ESTYLE_ROAD_ALL_SEPARATE */
351           struct sprite *dir[8];     /* all entries used */
352           /* ESTYLE_ROAD_PARITY_COMBINED */
353           struct {
354             struct sprite
355               *even[MAX_INDEX_HALF],    /* first unused */
356               *odd[MAX_INDEX_HALF];     /* first unused */
357           } combo;
358           /* ESTYLE_ALL_SEPARATE */
359           struct sprite *total[MAX_INDEX_VALID];
360           struct river_sprites rivers;
361         } ru;
362       } road;
363     } u;
364   } extras[MAX_EXTRA_TYPES];
365   struct {
366     struct sprite
367       *main[EDGE_COUNT],
368       *city[EDGE_COUNT],
369       *worked[EDGE_COUNT],
370       *unavailable,
371       *nonnative,
372       *selected[EDGE_COUNT],
373       *coastline[EDGE_COUNT],
374       *borders[EDGE_COUNT][2];
375   } grid;
376   struct {
377     struct sprite_vector overlays;
378   } colors;
379   struct {
380     struct sprite *color; /* Generic background color */
381     struct sprite *graphic; /* Generic background graphic */
382   } background;
383   struct {
384     struct sprite *grid_borders[EDGE_COUNT][2];
385     struct sprite *color;
386     struct sprite *background;
387   } player[MAX_NUM_PLAYER_SLOTS];
388 
389   struct drawing_data *drawing[MAX_NUM_ITEMS];
390 };
391 
392 struct specfile {
393   struct sprite *big_sprite;
394   char *file_name;
395 };
396 
397 #define SPECLIST_TAG specfile
398 #define SPECLIST_TYPE struct specfile
399 #include "speclist.h"
400 
401 #define specfile_list_iterate(list, pitem) \
402     TYPED_LIST_ITERATE(struct specfile, list, pitem)
403 #define specfile_list_iterate_end  LIST_ITERATE_END
404 
405 /*
406  * Information about an individual sprite. All fields except 'sprite' are
407  * filled at the time of the scan of the specfile. 'Sprite' is
408  * set/cleared on demand in load_sprite/unload_sprite.
409  */
410 struct small_sprite {
411   int ref_count;
412 
413   /* The sprite is in this file. */
414   char *file;
415 
416   /* Or, the sprite is in this file at the location. */
417   struct specfile *sf;
418   int x, y, width, height;
419 
420   /* A little more (optional) data. */
421   int hot_x, hot_y;
422 
423   struct sprite *sprite;
424 };
425 
426 /* 'struct small_sprite_list' and related functions. */
427 #define SPECLIST_TAG small_sprite
428 #define SPECLIST_TYPE struct small_sprite
429 #include "speclist.h"
430 #define small_sprite_list_iterate(list, pitem)                              \
431   TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
432 #define small_sprite_list_iterate_end LIST_ITERATE_END
433 
434 /* 'struct sprite_hash' and related functions. */
435 #define SPECHASH_TAG sprite
436 #define SPECHASH_ASTR_KEY_TYPE
437 #define SPECHASH_IDATA_TYPE struct small_sprite *
438 #include "spechash.h"
439 #define sprite_hash_iterate(hash, tag_name, sprite)                         \
440   TYPED_HASH_ITERATE(const char *, struct small_sprite *,                   \
441                      hash, tag_name, sprite)
442 #define sprite_hash_iterate_end HASH_ITERATE_END
443 
444 /* 'struct drawing_hash' and related functions. */
445 static void drawing_data_destroy(struct drawing_data *draw);
446 
447 #define SPECHASH_TAG drawing
448 #define SPECHASH_CSTR_KEY_TYPE
449 #define SPECHASH_IDATA_TYPE struct drawing_data *
450 #define SPECHASH_IDATA_FREE drawing_data_destroy
451 #include "spechash.h"
452 
453 #define SPECHASH_TAG estyle
454 #define SPECHASH_ASTR_KEY_TYPE
455 #define SPECHASH_ENUM_DATA_TYPE extrastyle_id
456 #include "spechash.h"
457 
458 struct tileset {
459   char name[512];
460   char given_name[MAX_LEN_NAME];
461   char version[MAX_LEN_NAME];
462   int priority;
463 
464   char *summary;
465   char *description;
466   float scale;
467 
468   enum ts_type type;
469   int hex_width, hex_height;
470   int ts_topo_idx;
471 
472   int normal_tile_width, normal_tile_height;
473   int full_tile_width, full_tile_height;
474   int unit_tile_width, unit_tile_height;
475   int small_sprite_width, small_sprite_height;
476 
477   int max_upkeep_height;
478 
479   char *main_intro_filename;
480   char *minimap_intro_filename;
481 
482   int city_names_font_size, city_productions_font_size;
483 
484   enum fog_style fogstyle;
485   enum darkness_style darkness_style;
486   int darkness_layer;
487 
488   int unit_flag_offset_x, unit_flag_offset_y;
489   int city_flag_offset_x, city_flag_offset_y;
490   int unit_offset_x, unit_offset_y;
491   int city_offset_x, city_offset_y;
492 
493   int citybar_offset_y;
494   int tilelabel_offset_y;
495   int activity_offset_x;
496   int activity_offset_y;
497   int occupied_offset_x;
498   int occupied_offset_y;
499   int unit_upkeep_offset_y;
500   int unit_upkeep_small_offset_y;
501 
502 #define NUM_CORNER_DIRS 4
503 #define TILES_PER_CORNER 4
504   int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
505   int num_index_valid, num_index_cardinal;
506   enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
507 
508   struct tileset_layer {
509     char **match_types;
510     size_t match_count;
511   } layers[MAX_NUM_LAYERS];
512 
513   struct specfile_list *specfiles;
514   struct small_sprite_list *small_sprites;
515 
516   /* This hash table maps tilespec tags to struct small_sprites. */
517   struct sprite_hash *sprite_hash;
518 
519   /* This hash table maps terrain graphic strings to drawing data. */
520   struct drawing_hash *tile_hash;
521 
522   struct estyle_hash *estyle_hash;
523 
524   struct named_sprites sprites;
525 
526   struct color_system *color_system;
527 
528   struct extra_type_list *style_lists[ESTYLE_COUNT];
529 
530   struct extra_type_list *flagged_bases_list;
531 
532   int num_preferred_themes;
533   char** preferred_themes;
534 };
535 
536 struct tileset *tileset;
537 struct tileset *unscaled_tileset;
538 
539 int focus_unit_state = 0;
540 
541 static bool tileset_update = FALSE;
542 
543 
544 static int fill_unit_type_sprite_array(const struct tileset *t,
545                                        struct drawn_sprite *sprs,
546                                        const struct unit_type *putype,
547                                        enum direction8 facing);
548 static int fill_unit_sprite_array(const struct tileset *t,
549                                   struct drawn_sprite *sprs,
550                                   const struct unit *punit,
551                                   bool stack, bool backdrop);
552 static bool load_river_sprites(struct tileset *t,
553                                struct river_sprites *store, const char *tag_pfx);
554 
555 static void tileset_setup_base(struct tileset *t,
556                                const struct extra_type *pextra);
557 static void tileset_setup_road(struct tileset *t,
558                                struct extra_type *pextra);
559 
560 static bool is_extra_drawing_enabled(struct extra_type *pextra);
561 
562 static int fill_basic_road_sprite_array(const struct tileset *t,
563                                         struct drawn_sprite *sprs,
564                                         const struct extra_type *pextra);
565 static int fill_basic_base_sprite_array(const struct tileset *t,
566                                         struct drawn_sprite *sprs,
567                                         const struct extra_type *pextra);
568 
569 static void tileset_player_free(struct tileset *t, int plrid);
570 
571 /****************************************************************************
572   Called when ever there's problem in ruleset/tileset compatibility
573 ****************************************************************************/
tileset_error(enum log_level level,const char * format,...)574 void tileset_error(enum log_level level, const char *format, ...)
575 {
576   char buf[2048];
577   va_list args;
578 
579   va_start(args, format);
580   fc_vsnprintf(buf, sizeof(buf), format, args);
581   va_end(args);
582 
583   log_base(level, "%s", buf);
584 
585   if (level <= LOG_NORMAL) {
586     show_tileset_error(buf);
587   }
588 
589   if (level == LOG_FATAL) {
590     exit(EXIT_FAILURE);
591   }
592 }
593 
594 /****************************************************************************
595   Create a new drawing data.
596 ****************************************************************************/
drawing_data_new(void)597 static struct drawing_data *drawing_data_new(void)
598 {
599   struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
600 
601   draw->name = NULL;
602 
603   return draw;
604 }
605 
606 /****************************************************************************
607   Free a drawing data.
608 ****************************************************************************/
drawing_data_destroy(struct drawing_data * draw)609 static void drawing_data_destroy(struct drawing_data *draw)
610 {
611   int i;
612 
613   fc_assert_ret(NULL != draw);
614 
615   if (draw->name != NULL) {
616     free(draw->name);
617   }
618   for (i = 0; i < 4; i++) {
619     if (draw->blend[i]) {
620       free_sprite(draw->blend[i]);
621     }
622   }
623   for (i = 0; i < draw->num_layers; i++) {
624     int vec_size = sprite_vector_size(&draw->layer[i].allocated);
625     int j;
626 
627     for (j = 0; j < vec_size; j++) {
628       free_sprite(draw->layer[i].allocated.p[j]);
629     }
630 
631     sprite_vector_free(&draw->layer[i].base);
632     sprite_vector_free(&draw->layer[i].allocated);
633     free(draw->layer[i].cells);
634   }
635   free(draw);
636 }
637 
638 /****************************************************************************
639   Return unscaled tileset if it exists, or default otherwise
640 ****************************************************************************/
get_tileset(void)641 struct tileset* get_tileset(void)
642 {
643   if (unscaled_tileset != NULL) {
644     return unscaled_tileset;
645   } else {
646     return tileset;
647   }
648 }
649 
650 /****************************************************************************
651   Return the name of the given tileset.
652 ****************************************************************************/
tileset_basename(const struct tileset * t)653 const char *tileset_basename(const struct tileset *t)
654 {
655   return t->name;
656 }
657 
658 /****************************************************************************
659   Return whether the current tileset is isometric.
660 ****************************************************************************/
tileset_is_isometric(const struct tileset * t)661 bool tileset_is_isometric(const struct tileset *t)
662 {
663   return t->type == TS_ISOMETRIC;
664 }
665 
666 /****************************************************************************
667   Return the hex_width of the current tileset. For iso-hex tilesets this
668   value will be > 0 and is_isometric will be set.
669 ****************************************************************************/
tileset_hex_width(const struct tileset * t)670 int tileset_hex_width(const struct tileset *t)
671 {
672   return t->hex_width;
673 }
674 
675 /****************************************************************************
676   Return the hex_height of the current tileset. For hex tilesets this
677   value will be > 0 and is_isometric will be set.
678 ****************************************************************************/
tileset_hex_height(const struct tileset * t)679 int tileset_hex_height(const struct tileset *t)
680 {
681   return t->hex_height;
682 }
683 
684 /****************************************************************************
685   Return the tile width of the current tileset.  This is the tesselation
686   width of the tiled plane.  This means it's the width of the bounding box
687   of the basic map tile.
688 
689   For best results:
690     - The value should be even (or a multiple of 4 in iso-view).
691     - In iso-view, the width should be twice the height (to give a
692       perspective of 30 degrees above the horizon).
693     - In non-iso-view, width and height should be equal (overhead
694       perspective).
695     - In hex or iso-hex view, remember this is the tesselation vector.
696       hex_width and hex_height then give the size of the side of the
697       hexagon.  Calculating the dimensions of a "regular" hexagon or
698       iso-hexagon may be tricky.
699   However these requirements are not absolute and callers should not
700   depend on them (although some do).
701 ****************************************************************************/
tileset_tile_width(const struct tileset * t)702 int tileset_tile_width(const struct tileset *t)
703 {
704   return t->normal_tile_width;
705 }
706 
707 /****************************************************************************
708   Return the tile height of the current tileset.  This is the tesselation
709   height of the tiled plane.  This means it's the height of the bounding box
710   of the basic map tile.
711 
712   See also tileset_tile_width.
713 ****************************************************************************/
tileset_tile_height(const struct tileset * t)714 int tileset_tile_height(const struct tileset *t)
715 {
716   return t->normal_tile_height;
717 }
718 
719 /****************************************************************************
720   Return the full tile width of the current tileset.  This is the maximum
721   width that any mapview sprite will have.
722 
723   Note: currently this is always equal to the tile width.
724 ****************************************************************************/
tileset_full_tile_width(const struct tileset * t)725 int tileset_full_tile_width(const struct tileset *t)
726 {
727   return t->full_tile_width;
728 }
729 
730 /****************************************************************************
731   Return the full tile height of the current tileset.  This is the maximum
732   height that any mapview sprite will have.  This may be greater than the
733   tile width in which case the extra area is above the "normal" tile.
734 
735   Some callers assume the full height is 50% larger than the height in
736   iso-view, and equal in non-iso view.
737 ****************************************************************************/
tileset_full_tile_height(const struct tileset * t)738 int tileset_full_tile_height(const struct tileset *t)
739 {
740   return t->full_tile_height;
741 }
742 
743 /****************************************************************************
744   Return the unit tile width of the current tileset.
745 ****************************************************************************/
tileset_unit_width(const struct tileset * t)746 int tileset_unit_width(const struct tileset *t)
747 {
748   return t->unit_tile_width;
749 }
750 
751 /****************************************************************************
752   Return the unit tile height of the current tileset.
753 ****************************************************************************/
tileset_unit_height(const struct tileset * t)754 int tileset_unit_height(const struct tileset *t)
755 {
756   return t->unit_tile_height;
757 }
758 
759 /****************************************************************************
760   Calculate the height of a unit upkeep icons.
761 ****************************************************************************/
calculate_max_upkeep_height(const struct tileset * t)762 static int calculate_max_upkeep_height(const struct tileset *t)
763 {
764   int i;
765   int max = 0;
766 
767   for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
768     if (t->sprites.upkeep.unhappy[i] != NULL) {
769       int width, height;
770 
771       /* TODO: We want only height, getting the width might waste CPU
772        * depending on gui-specific implementation. */
773       get_sprite_dimensions(t->sprites.upkeep.unhappy[i], &width, &height);
774 
775       max = MAX(max, height);
776     }
777   }
778 
779   output_type_iterate(o) {
780     for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
781       if (t->sprites.upkeep.output[o][i] != NULL) {
782         int width, height;
783 
784         /* TODO: We want only height, getting the width might waste CPU
785          * depending on gui-specific implementation. */
786         get_sprite_dimensions(t->sprites.upkeep.output[o][i], &width, &height);
787 
788         max = MAX(max, height);
789       }
790     }
791   } output_type_iterate_end;
792 
793   return max;
794 }
795 
796 /****************************************************************************
797   Get the height of a unit upkeep icons.
798 ****************************************************************************/
tileset_upkeep_height(const struct tileset * t)799 static int tileset_upkeep_height(const struct tileset *t)
800 {
801   /* Return cached value */
802   return t->max_upkeep_height;
803 }
804 
805 /****************************************************************************
806   Suitable canvas height for a unit icon that includes upkeep sprites.
807 ****************************************************************************/
tileset_unit_with_upkeep_height(const struct tileset * t)808 int tileset_unit_with_upkeep_height(const struct tileset *t)
809 {
810   int uk_bottom = tileset_unit_layout_offset_y(tileset) + tileset_upkeep_height(tileset);
811   int u_bottom = tileset_unit_height(tileset);
812 
813   return MAX(uk_bottom, u_bottom);
814 }
815 
816 /****************************************************************************
817   Suitable canvas height for a unit icon that includes upkeep sprites,
818   using small space layout.
819 ****************************************************************************/
tileset_unit_with_small_upkeep_height(const struct tileset * t)820 int tileset_unit_with_small_upkeep_height(const struct tileset *t)
821 {
822   return tileset_unit_layout_small_offset_y(tileset) + tileset_upkeep_height(tileset);
823 }
824 
825 /****************************************************************************
826   Offset to layout extra unit sprites, such as upkeep.
827 ****************************************************************************/
tileset_unit_layout_offset_y(const struct tileset * t)828 int tileset_unit_layout_offset_y(const struct tileset *t)
829 {
830   return t->unit_upkeep_offset_y;
831 }
832 
833 /****************************************************************************
834   Offset to layout extra unit sprites, such as upkeep, requesting small
835   space layout.
836 ****************************************************************************/
tileset_unit_layout_small_offset_y(const struct tileset * t)837 int tileset_unit_layout_small_offset_y(const struct tileset *t)
838 {
839   return t->unit_upkeep_small_offset_y;
840 }
841 
842 /****************************************************************************
843   Return the small sprite width of the current tileset.  The small sprites
844   are used for various theme graphics (e.g., citymap citizens/specialists
845   as well as panel indicator icons).
846 ****************************************************************************/
tileset_small_sprite_width(const struct tileset * t)847 int tileset_small_sprite_width(const struct tileset *t)
848 {
849   return t->small_sprite_width;
850 }
851 
852 /****************************************************************************
853   Return the offset from the origin of the city tile at which to place the
854   city bar text.
855 ****************************************************************************/
tileset_citybar_offset_y(const struct tileset * t)856 int tileset_citybar_offset_y(const struct tileset *t)
857 {
858   return t->citybar_offset_y;
859 }
860 
861 /****************************************************************************
862   Return the offset from the origin of the tile at which to place the
863   label text.
864 ****************************************************************************/
tileset_tilelabel_offset_y(const struct tileset * t)865 int tileset_tilelabel_offset_y(const struct tileset *t)
866 {
867   return t->tilelabel_offset_y;
868 }
869 
870 /****************************************************************************
871   Returns tileset scale
872 ****************************************************************************/
tileset_scale(const struct tileset * t)873 float tileset_scale(const struct tileset *t)
874 {
875   return tileset->scale;
876 }
877 
878 /****************************************************************************
879   Return the small sprite height of the current tileset.  The small sprites
880   are used for various theme graphics (e.g., citymap citizens/specialists
881   as well as panel indicator icons).
882 ****************************************************************************/
tileset_small_sprite_height(const struct tileset * t)883 int tileset_small_sprite_height(const struct tileset *t)
884 {
885   return t->small_sprite_height;
886 }
887 
888 /****************************************************************************
889   Return the path within the data directories where the main intro graphics
890   file can be found.  (It is left up to the GUI code to load and unload this
891   file.)
892 ****************************************************************************/
tileset_main_intro_filename(const struct tileset * t)893 const char *tileset_main_intro_filename(const struct tileset *t)
894 {
895   return t->main_intro_filename;
896 }
897 
898 /****************************************************************************
899   Return the path within the data directories where the mini intro graphics
900   file can be found.  (It is left up to the GUI code to load and unload this
901   file.)
902 ****************************************************************************/
tileset_mini_intro_filename(const struct tileset * t)903 const char *tileset_mini_intro_filename(const struct tileset *t)
904 {
905   return t->minimap_intro_filename;
906 }
907 
908 /****************************************************************************
909   Return the number of possible colors for city overlays.
910 ****************************************************************************/
tileset_num_city_colors(const struct tileset * t)911 int tileset_num_city_colors(const struct tileset *t)
912 {
913   return t->sprites.city.worked_tile_overlay.size;
914 }
915 
916 /****************************************************************************
917   Return TRUE if the client will use the code to generate the fog.
918 ****************************************************************************/
tileset_use_hard_coded_fog(const struct tileset * t)919 bool tileset_use_hard_coded_fog(const struct tileset *t)
920 {
921   return FOG_AUTO == t->fogstyle;
922 }
923 
924 /**************************************************************************
925   Initialize.
926 **************************************************************************/
tileset_new(void)927 static struct tileset *tileset_new(void)
928 {
929   struct tileset *t = fc_calloc(1, sizeof(*t));
930 
931   t->specfiles = specfile_list_new();
932   t->small_sprites = small_sprite_list_new();
933   return t;
934 }
935 
936 /**************************************************************************
937   Return the tileset name of the direction.  This is similar to
938   dir_get_name but you shouldn't change this or all tilesets will break.
939 **************************************************************************/
dir_get_tileset_name(enum direction8 dir)940 static const char *dir_get_tileset_name(enum direction8 dir)
941 {
942   switch (dir) {
943   case DIR8_NORTH:
944     return "n";
945   case DIR8_NORTHEAST:
946     return "ne";
947   case DIR8_EAST:
948     return "e";
949   case DIR8_SOUTHEAST:
950     return "se";
951   case DIR8_SOUTH:
952     return "s";
953   case DIR8_SOUTHWEST:
954     return "sw";
955   case DIR8_WEST:
956     return "w";
957   case DIR8_NORTHWEST:
958     return "nw";
959   }
960   log_error("Wrong direction8 variant: %d.", dir);
961   return "";
962 }
963 
964 /****************************************************************************
965   Return TRUE iff the dir is valid in this tileset.
966 ****************************************************************************/
is_valid_tileset_dir(const struct tileset * t,enum direction8 dir)967 static bool is_valid_tileset_dir(const struct tileset *t,
968 				 enum direction8 dir)
969 {
970   if (t->hex_width > 0) {
971     return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
972   } else if (t->hex_height > 0) {
973     return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
974   } else {
975     return TRUE;
976   }
977 }
978 
979 /****************************************************************************
980   Return TRUE iff the dir is cardinal in this tileset.
981 
982   "Cardinal", in this sense, means that a tile will share a border with
983   another tile in the direction rather than sharing just a single vertex.
984 ****************************************************************************/
is_cardinal_tileset_dir(const struct tileset * t,enum direction8 dir)985 static bool is_cardinal_tileset_dir(const struct tileset *t,
986 				    enum direction8 dir)
987 {
988   if (t->hex_width > 0 || t->hex_height > 0) {
989     return is_valid_tileset_dir(t, dir);
990   } else {
991     return (dir == DIR8_NORTH || dir == DIR8_EAST
992             || dir == DIR8_SOUTH || dir == DIR8_WEST);
993   }
994 }
995 
996 /**********************************************************************
997   Convert properties of the actual topology to an index of different
998   tileset topology types.
999 ***********************************************************************/
ts_topology_index(int actual_topology)1000 static int ts_topology_index(int actual_topology)
1001 {
1002   int idx;
1003 
1004   if ((actual_topology & TF_HEX)
1005       && (actual_topology & TF_ISO)) {
1006     idx = TS_TOPO_ISOHEX;
1007   } else if (actual_topology & TF_ISO) {
1008     idx = TS_TOPO_ISO;
1009   } else if (actual_topology & TF_HEX) {
1010     idx = TS_TOPO_HEX;
1011   } else {
1012     idx = TS_TOPO_OVERHEAD;
1013   }
1014 
1015   return idx;
1016 }
1017 
1018 /**********************************************************************
1019   Returns a static list of tilesets available on the system by
1020   searching all data directories for files matching TILESPEC_SUFFIX.
1021 ***********************************************************************/
get_tileset_list(const struct option * poption)1022 const struct strvec *get_tileset_list(const struct option *poption)
1023 {
1024   static struct strvec *tilesets[4] = { NULL, NULL, NULL, NULL };
1025   int topo = option_get_cb_data(poption);
1026   int idx;
1027 
1028   idx = ts_topology_index(topo);
1029 
1030   fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), NULL);
1031 
1032   if (tilesets[idx] == NULL) {
1033     /* Note: this means you must restart the client after installing a new
1034        tileset. */
1035     struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1036 
1037     tilesets[idx] = strvec_new();
1038     strvec_iterate(list, file) {
1039       struct tileset *t = tileset_read_toplevel(file, FALSE, topo, 1.0f);
1040 
1041       if (t) {
1042         strvec_append(tilesets[idx], file);
1043         tileset_free(t);
1044       }
1045     } strvec_iterate_end;
1046     strvec_destroy(list);
1047   }
1048 
1049   return tilesets[idx];
1050 }
1051 
1052 /**********************************************************************
1053   Gets full filename for tilespec file, based on input name.
1054   Returned data is allocated, and freed by user as required.
1055   Input name may be null, in which case uses default.
1056   Falls back to default if can't find specified name;
1057   dies if can't find default.
1058 ***********************************************************************/
tilespec_fullname(const char * tileset_name)1059 static char *tilespec_fullname(const char *tileset_name)
1060 {
1061   if (tileset_name) {
1062     char fname[strlen(tileset_name) + strlen(TILESPEC_SUFFIX) + 1];
1063     const char *dname;
1064 
1065     fc_snprintf(fname, sizeof(fname),
1066                 "%s%s", tileset_name, TILESPEC_SUFFIX);
1067 
1068     dname = fileinfoname(get_data_dirs(), fname);
1069 
1070     if (dname) {
1071       return fc_strdup(dname);
1072     }
1073   }
1074 
1075   return NULL;
1076 }
1077 
1078 /**********************************************************************
1079   Checks options in filename match what we require and support.
1080   Die if not.
1081   'which' should be "tilespec" or "spec".
1082 ***********************************************************************/
check_tilespec_capabilities(struct section_file * file,const char * which,const char * us_capstr,const char * filename,bool verbose)1083 static bool check_tilespec_capabilities(struct section_file *file,
1084 					const char *which,
1085 					const char *us_capstr,
1086 					const char *filename,
1087                                         bool verbose)
1088 {
1089   enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
1090 
1091   const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
1092 
1093   if (NULL == file_capstr) {
1094     log_base(level, "\"%s\": %s file doesn't have a capability string",
1095              filename, which);
1096     return FALSE;
1097   }
1098   if (!has_capabilities(us_capstr, file_capstr)) {
1099     log_base(level, "\"%s\": %s file appears incompatible:",
1100              filename, which);
1101     log_base(level, "  datafile options: %s", file_capstr);
1102     log_base(level, "  supported options: %s", us_capstr);
1103     return FALSE;
1104   }
1105   if (!has_capabilities(file_capstr, us_capstr)) {
1106     log_base(level, "\"%s\": %s file requires option(s) "
1107              "that client doesn't support:", filename, which);
1108     log_base(level, "  datafile options: %s", file_capstr);
1109     log_base(level, "  supported options: %s", us_capstr);
1110     return FALSE;
1111   }
1112 
1113   return TRUE;
1114 }
1115 
1116 /**********************************************************************
1117   Frees the tilespec toplevel data, in preparation for re-reading it.
1118 
1119   See tilespec_read_toplevel().
1120 ***********************************************************************/
tileset_free_toplevel(struct tileset * t)1121 static void tileset_free_toplevel(struct tileset *t)
1122 {
1123   int i, j;
1124 
1125   if (t->main_intro_filename) {
1126     free(t->main_intro_filename);
1127     t->main_intro_filename = NULL;
1128   }
1129   if (t->minimap_intro_filename) {
1130     free(t->minimap_intro_filename);
1131     t->minimap_intro_filename = NULL;
1132   }
1133 
1134   if (t->preferred_themes) {
1135     for (i = 0; i < t->num_preferred_themes; i++) {
1136       free(t->preferred_themes[i]);
1137     }
1138     free(t->preferred_themes);
1139     t->preferred_themes = NULL;
1140   }
1141   t->num_preferred_themes = 0;
1142 
1143   if (t->tile_hash) {
1144     drawing_hash_destroy(t->tile_hash);
1145     t->tile_hash = NULL; /* Helpful for sanity. */
1146   }
1147   if (t->estyle_hash) {
1148     estyle_hash_destroy(t->estyle_hash);
1149     t->estyle_hash = NULL;
1150   }
1151   for (i = 0; i < ESTYLE_COUNT; i++) {
1152     if (t->style_lists[i] != NULL) {
1153       extra_type_list_destroy(t->style_lists[i]);
1154       t->style_lists[i] = NULL;
1155     }
1156   }
1157 
1158   if (t->flagged_bases_list != NULL) {
1159     extra_type_list_destroy(t->flagged_bases_list);
1160     t->flagged_bases_list = NULL;
1161   }
1162 
1163   for (i = 0; i < MAX_NUM_LAYERS; i++) {
1164     struct tileset_layer *tslp = &t->layers[i];
1165 
1166     if (tslp->match_types) {
1167       for (j = 0; j < tslp->match_count; j++) {
1168 	free(tslp->match_types[j]);
1169       }
1170       free(tslp->match_types);
1171       tslp->match_types = NULL;
1172     }
1173   }
1174 
1175   if (t->color_system) {
1176     color_system_free(t->color_system);
1177     t->color_system = NULL;
1178   }
1179 
1180   if (t->summary != NULL) {
1181     free(t->summary);
1182     t->summary = NULL;
1183   }
1184   if (t->description != NULL) {
1185     free(t->description);
1186     t->description = NULL;
1187   }
1188 }
1189 
1190 /**************************************************************************
1191   Clean up.
1192 **************************************************************************/
tileset_free(struct tileset * t)1193 void tileset_free(struct tileset *t)
1194 {
1195   int i;
1196 
1197   tileset_free_tiles(t);
1198   tileset_free_toplevel(t);
1199   for (i = 0; i < ARRAY_SIZE(t->sprites.player); i++) {
1200     tileset_player_free(t, i);
1201   }
1202   specfile_list_destroy(t->specfiles);
1203   small_sprite_list_destroy(t->small_sprites);
1204   free(t);
1205 }
1206 
1207 /**********************************************************************
1208   Read a new tilespec in when first starting the game.
1209 
1210   Call this function with the (guessed) name of the tileset, when
1211   starting the client.
1212 
1213   Returns TRUE iff tileset with suggested tileset_name was loaded.
1214 ***********************************************************************/
tilespec_try_read(const char * tileset_name,bool verbose,int topo_id,bool global_default)1215 bool tilespec_try_read(const char *tileset_name, bool verbose, int topo_id,
1216                        bool global_default)
1217 {
1218   bool original;
1219 
1220   if (tileset_name == NULL
1221       || !(tileset = tileset_read_toplevel(tileset_name, verbose,
1222                                            topo_id, 1.0f))) {
1223     struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1224 
1225     original = FALSE;
1226     strvec_iterate(list, file) {
1227       struct tileset *t = tileset_read_toplevel(file, FALSE, topo_id, 1.0f);
1228 
1229       if (t) {
1230         if (!tileset) {
1231           tileset = t;
1232         } else if (t->priority > tileset->priority
1233                    || (topo_id >= 0
1234                        && tileset_topo_index(tileset) != tileset_topo_index(t))) {
1235           tileset_free(tileset);
1236           tileset = t;
1237         } else {
1238           tileset_free(t);
1239         }
1240       }
1241     } strvec_iterate_end;
1242     strvec_destroy(list);
1243 
1244     if (!tileset) {
1245       tileset_error(LOG_FATAL, _("No usable default tileset found, aborting!"));
1246     }
1247 
1248     log_verbose("Trying tileset \"%s\".", tileset->name);
1249   } else {
1250     original = TRUE;
1251   }
1252   option_set_default_ts(tileset);
1253 
1254   if (global_default) {
1255     sz_strlcpy(gui_options.default_tileset_name, tileset_basename(tileset));
1256   }
1257 
1258   return original;
1259 }
1260 
1261 /**********************************************************************
1262   Read a new tilespec in from scratch.
1263 
1264   Unlike the initial reading code, which reads pieces one at a time,
1265   this gets rid of the old data and reads in the new all at once.  If the
1266   new tileset fails to load the old tileset may be reloaded; otherwise the
1267   client will exit.  If a NULL name is given the current tileset will be
1268   reread.
1269 
1270   It will also call the necessary functions to redraw the graphics.
1271 
1272   Returns TRUE iff new tileset has been succesfully loaded.
1273 ***********************************************************************/
tilespec_reread(const char * new_tileset_name,bool game_fully_initialized,float scale)1274 bool tilespec_reread(const char *new_tileset_name,
1275                      bool game_fully_initialized, float scale)
1276 {
1277   int id;
1278   struct tile *center_tile;
1279   enum client_states state = client_state();
1280   const char *name = new_tileset_name ? new_tileset_name : tileset->name;
1281   char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1282   bool new_tileset_in_use;
1283   int ts_topo;
1284 
1285   /* Make local copies since these values may be freed down below */
1286   sz_strlcpy(tileset_name, name);
1287   sz_strlcpy(old_name, tileset->name);
1288 
1289   log_normal(_("Loading tileset \"%s\"."), tileset_name);
1290 
1291   /* Step 0:  Record old data.
1292    *
1293    * We record the current mapcanvas center, etc.
1294    */
1295   center_tile = get_center_tile_mapcanvas();
1296 
1297   /* Step 1:  Cleanup.
1298    *
1299    * Free old tileset or keep it in memeory if we are loading the same
1300    * tileset with scaling and old one was not scaled.
1301    */
1302 
1303   if (strcmp(tileset_name, old_name) == 0 && tileset->scale == 1.0f
1304       && scale != 1.0f) {
1305     if (unscaled_tileset) {
1306       tileset_free(unscaled_tileset);
1307     }
1308     unscaled_tileset = tileset;
1309   } else {
1310     tileset_free(tileset);
1311   }
1312 
1313   /* Step 2:  Read.
1314    *
1315    * We read in the new tileset.  This should be pretty straightforward.
1316    */
1317   tileset = tileset_read_toplevel(tileset_name, FALSE, -1, scale);
1318   if (tileset != NULL) {
1319     new_tileset_in_use = TRUE;
1320   } else {
1321     new_tileset_in_use = FALSE;
1322 
1323     if (!(tileset = tileset_read_toplevel(old_name, FALSE, -1, scale))) {
1324       /* Always fails. */
1325       fc_assert_exit_msg(NULL != tileset,
1326                          "Failed to re-read the currently loaded tileset.");
1327     }
1328   }
1329   tileset_load_tiles(tileset);
1330   if (game_fully_initialized) {
1331     tileset_use_preferred_theme(tileset);
1332   }
1333 
1334   if (game_fully_initialized) {
1335     if (game.client.ruleset_ready) {
1336       tileset_background_init(tileset);
1337     } /* else we'll get round to it on PACKET_RULESET_GAME */
1338     players_iterate(pplayer) {
1339       tileset_player_init(tileset, pplayer);
1340     } players_iterate_end;
1341     boot_help_texts(); /* "About Current Tileset" */
1342   }
1343 
1344   /* Step 3: Setup
1345    *
1346    * This is a seriously sticky problem.  On startup, we build a hash
1347    * from all the sprite data. Then, when we connect to a server, the
1348    * server sends us ruleset data a piece at a time and we use this data
1349    * to assemble the sprite structures.  But if we change while connected
1350    *  we have to reassemble all of these.  This should just involve
1351    * calling tilespec_setup_*** on everything.  But how do we tell what
1352    * "everything" is?
1353    *
1354    * The below code just does things straightforwardly, by setting up
1355    * each possible sprite again.  Hopefully it catches everything, and
1356    * doesn't mess up too badly if we change tilesets while not connected
1357    * to a server.
1358    */
1359   if (!game.client.ruleset_ready) {
1360     /* The ruleset data is not sent until this point. */
1361     return new_tileset_in_use;
1362   }
1363 
1364   if (tileset_map_topo_compatible(game.map.topology_id, tileset, &ts_topo)
1365       == TOPO_INCOMP_HARD) {
1366     tileset_error(LOG_NORMAL, _("Map topology (%s) and tileset (%s) incompatible."),
1367                   describe_topology(game.map.topology_id), describe_topology(ts_topo));
1368   }
1369 
1370   terrain_type_iterate(pterrain) {
1371     tileset_setup_tile_type(tileset, pterrain);
1372   } terrain_type_iterate_end;
1373   resource_type_iterate(presource) {
1374     tileset_setup_resource(tileset, presource);
1375   } resource_type_iterate_end;
1376   unit_type_iterate(punittype) {
1377     tileset_setup_unit_type(tileset, punittype);
1378   } unit_type_iterate_end;
1379   governments_iterate(gov) {
1380     tileset_setup_government(tileset, gov);
1381   } governments_iterate_end;
1382   extra_type_iterate(pextra) {
1383     tileset_setup_extra(tileset, pextra);
1384   } extra_type_iterate_end;
1385   nations_iterate(pnation) {
1386     tileset_setup_nation_flag(tileset, pnation);
1387   } nations_iterate_end;
1388   improvement_iterate(pimprove) {
1389     tileset_setup_impr_type(tileset, pimprove);
1390   } improvement_iterate_end;
1391   advance_iterate(A_FIRST, padvance) {
1392     tileset_setup_tech_type(tileset, padvance);
1393   } advance_iterate_end;
1394   specialist_type_iterate(sp) {
1395     tileset_setup_specialist_type(tileset, sp);
1396   } specialist_type_iterate_end;
1397 
1398   for (id = 0; id < game.control.styles_count; id++) {
1399     tileset_setup_city_tiles(tileset, id);
1400   }
1401 
1402   if (state < C_S_RUNNING) {
1403     /* Below redraws do not apply before this. */
1404     return new_tileset_in_use;
1405   }
1406 
1407   /* Step 4:  Draw.
1408    *
1409    * Do any necessary redraws.
1410    */
1411   generate_citydlg_dimensions();
1412   tileset_changed();
1413   can_slide = FALSE;
1414   center_tile_mapcanvas(center_tile);
1415   /* update_map_canvas_visible forces a full redraw.  Otherwise with fast
1416    * drawing we might not get one.  Of course this is slower. */
1417   update_map_canvas_visible();
1418   can_slide = TRUE;
1419 
1420   return new_tileset_in_use;
1421 }
1422 
1423 /**************************************************************************
1424   This is merely a wrapper for tilespec_reread (above) for use in
1425   options.c and the client local options dialog.
1426 **************************************************************************/
tilespec_reread_callback(struct option * poption)1427 void tilespec_reread_callback(struct option *poption)
1428 {
1429   const char *tileset_name;
1430   enum client_states state = client_state();
1431 
1432   if ((state == C_S_RUNNING || state == C_S_OVER)
1433       && option_get_cb_data(poption) != (game.map.topology_id & (TF_ISO | TF_HEX))) {
1434     /* Changed option was not for current topology */
1435     return;
1436   }
1437 
1438   tileset_name = option_str_get(poption);
1439 
1440   /* As it's going to be 'current' tileset, make it global default if
1441    * options saved. */
1442   sz_strlcpy(gui_options.default_tileset_name, tileset_name);
1443 
1444   fc_assert_ret(NULL != tileset_name && tileset_name[0] != '\0');
1445   tileset_update = TRUE;
1446   tilespec_reread(tileset_name, client.conn.established, 1.0f);
1447   tileset_update = FALSE;
1448   menus_init();
1449 }
1450 
1451 /**************************************************************************
1452   Read a new tilespec in from scratch. Keep UI frozen while tileset is
1453   partially loaded; in inconsistent state.
1454 
1455   See tilespec_reread() for details.
1456 **************************************************************************/
tilespec_reread_frozen_refresh(const char * tname)1457 void tilespec_reread_frozen_refresh(const char *tname)
1458 {
1459   tileset_update = TRUE;
1460   tilespec_reread(tname, TRUE, 1.0f);
1461   tileset_update = FALSE;
1462   menus_init();
1463 }
1464 
1465 /**************************************************************************
1466   Loads the given graphics file (found in the data path) into a newly
1467   allocated sprite.
1468 **************************************************************************/
load_gfx_file(const char * gfx_filename)1469 static struct sprite *load_gfx_file(const char *gfx_filename)
1470 {
1471   const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
1472   struct sprite *s;
1473 
1474   /* Try out all supported file extensions to find one that works. */
1475   while ((gfx_fileext = *gfx_fileexts++)) {
1476     const char *real_full_name;
1477     char full_name[strlen(gfx_filename) + strlen(".")
1478                    + strlen(gfx_fileext) + 1];
1479 
1480     sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
1481     if ((real_full_name = fileinfoname(get_data_dirs(), full_name))) {
1482       log_debug("trying to load gfx file \"%s\".", real_full_name);
1483       s = load_gfxfile(real_full_name);
1484       if (s) {
1485 	return s;
1486       }
1487     }
1488   }
1489 
1490   log_error("Could not load gfx file \"%s\".", gfx_filename);
1491   return NULL;
1492 }
1493 
1494 /**************************************************************************
1495   Ensure that the big sprite of the given spec file is loaded.
1496 **************************************************************************/
ensure_big_sprite(struct specfile * sf)1497 static void ensure_big_sprite(struct specfile *sf)
1498 {
1499   struct section_file *file;
1500   const char *gfx_filename;
1501 
1502   if (sf->big_sprite) {
1503     /* Looks like it's already loaded. */
1504     return;
1505   }
1506 
1507   /* Otherwise load it.  The big sprite will sometimes be freed and will have
1508    * to be reloaded, but most of the time it's just loaded once, the small
1509    * sprites are extracted, and then it's freed. */
1510   if (!(file = secfile_load(sf->file_name, TRUE))) {
1511     tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1512   }
1513 
1514   if (!check_tilespec_capabilities(file, "spec",
1515 				   SPEC_CAPSTR, sf->file_name, TRUE)) {
1516     tileset_error(LOG_FATAL, _("Incompatible tileset capabilities"));
1517   }
1518 
1519   gfx_filename = secfile_lookup_str(file, "file.gfx");
1520 
1521   sf->big_sprite = load_gfx_file(gfx_filename);
1522 
1523   if (!sf->big_sprite) {
1524     tileset_error(LOG_FATAL, _("Could not load gfx file for the spec file \"%s\"."),
1525                   sf->file_name);
1526   }
1527   secfile_destroy(file);
1528 }
1529 
1530 /**************************************************************************
1531   Scan all sprites declared in the given specfile.  This means that the
1532   positions of the sprites in the big_sprite are saved in the
1533   small_sprite structs.
1534 **************************************************************************/
scan_specfile(struct tileset * t,struct specfile * sf,bool duplicates_ok)1535 static void scan_specfile(struct tileset *t, struct specfile *sf,
1536 			  bool duplicates_ok)
1537 {
1538   struct section_file *file;
1539   struct section_list *sections;
1540   int i;
1541 
1542   if (!(file = secfile_load(sf->file_name, TRUE))) {
1543     tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1544   }
1545   if (!check_tilespec_capabilities(file, "spec",
1546 				   SPEC_CAPSTR, sf->file_name, TRUE)) {
1547     tileset_error(LOG_FATAL, _("Specfile %s has incompatible capabilities"), sf->file_name);
1548   }
1549 
1550   /* Currently unused */
1551   (void) secfile_entry_lookup(file, "info.artists");
1552 
1553   /* Not used here */
1554   (void) secfile_entry_lookup(file, "file.gfx");
1555 
1556   if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1557     section_list_iterate(sections, psection) {
1558       int j, k;
1559       int x_top_left, y_top_left, dx, dy;
1560       int pixel_border_x;
1561       int pixel_border_y;
1562       const char *sec_name = section_name(psection);
1563 
1564       pixel_border_x = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1565                                                   sec_name);
1566       pixel_border_y = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_y",
1567                                                   sec_name);
1568       pixel_border_x = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_x",
1569                                                   sec_name);
1570       if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1571           || !secfile_lookup_int(file, &y_top_left,
1572                                  "%s.y_top_left", sec_name)
1573           || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1574           || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1575         log_error("%s grid \"%s\" invalid: %s",
1576                   sf->file_name, sec_name, secfile_error());
1577         continue;
1578       }
1579 
1580       j = -1;
1581       while (NULL != secfile_entry_lookup(file, "%s.tiles%d.tag",
1582                                           sec_name, ++j)) {
1583         struct small_sprite *ss;
1584         int row, column;
1585         int xr, yb;
1586         const char **tags;
1587         size_t num_tags;
1588         int hot_x, hot_y;
1589 
1590         if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1591             || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1592                                    sec_name, j)
1593             || !(tags = secfile_lookup_str_vec(file, &num_tags,
1594                                                "%s.tiles%d.tag",
1595                                                sec_name, j))) {
1596           log_error("%s small sprite \"%s.tiles%d\" invalid: %s",
1597                     sf->file_name, sec_name, j, secfile_error());
1598           continue;
1599         }
1600         hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1601                                            sec_name, j);
1602         hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1603                                            sec_name, j);
1604 
1605         /* there must be at least 1 because of the while(): */
1606         fc_assert_action(num_tags > 0, continue);
1607 
1608         xr = x_top_left + (dx + pixel_border_x) * column;
1609         yb = y_top_left + (dy + pixel_border_y) * row;
1610 
1611         ss = fc_malloc(sizeof(*ss));
1612         ss->ref_count = 0;
1613         ss->file = NULL;
1614         ss->x = xr;
1615         ss->y = yb;
1616         ss->width = dx;
1617         ss->height = dy;
1618         ss->sf = sf;
1619         ss->sprite = NULL;
1620         ss->hot_x = hot_x;
1621         ss->hot_y = hot_y;
1622 
1623         small_sprite_list_prepend(t->small_sprites, ss);
1624 
1625         if (!duplicates_ok) {
1626           for (k = 0; k < num_tags; k++) {
1627             if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1628               log_error("warning: %s already has a sprite for \"%s\".",
1629                         tileset_name_get(t), tags[k]);
1630             }
1631           }
1632         } else {
1633           for (k = 0; k < num_tags; k++) {
1634             (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1635           }
1636         }
1637 
1638         free(tags);
1639         tags = NULL;
1640       }
1641     } section_list_iterate_end;
1642     section_list_destroy(sections);
1643   }
1644 
1645   /* Load "extra" sprites.  Each sprite is one file. */
1646   i = -1;
1647   while (NULL != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1648     struct small_sprite *ss;
1649     const char **tags;
1650     const char *filename;
1651     size_t num_tags, k;
1652     int hot_x, hot_y;
1653 
1654     if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1655                                         "extra.sprites%d.tag", i))
1656         || !(filename = secfile_lookup_str(file,
1657                                            "extra.sprites%d.file", i))) {
1658       log_error("%s extra sprite \"extra.sprites%d\" invalid: %s",
1659                 sf->file_name, i, secfile_error());
1660       continue;
1661     }
1662     hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1663     hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1664 
1665     ss = fc_malloc(sizeof(*ss));
1666     ss->ref_count = 0;
1667     ss->file = fc_strdup(filename);
1668     ss->sf = NULL;
1669     ss->sprite = NULL;
1670     ss->hot_x = hot_x;
1671     ss->hot_y = hot_y;
1672 
1673     small_sprite_list_prepend(t->small_sprites, ss);
1674 
1675     if (!duplicates_ok) {
1676       for (k = 0; k < num_tags; k++) {
1677         if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1678           log_error("warning: %s already have a sprite for \"%s\".",
1679                     tileset_name_get(t), tags[k]);
1680         }
1681       }
1682     } else {
1683       for (k = 0; k < num_tags; k++) {
1684         (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1685       }
1686     }
1687     free(tags);
1688   }
1689 
1690   secfile_check_unused(file);
1691   secfile_destroy(file);
1692 }
1693 
1694 /**********************************************************************
1695   Returns the correct name of the gfx file (with path and extension)
1696   Must be free'd when no longer used
1697 ***********************************************************************/
tilespec_gfx_filename(const char * gfx_filename)1698 static char *tilespec_gfx_filename(const char *gfx_filename)
1699 {
1700   const char  *gfx_current_fileext;
1701   const char **gfx_fileexts = gfx_fileextensions();
1702 
1703   while ((gfx_current_fileext = *gfx_fileexts++)) {
1704     const char *real_full_name;
1705     char *full_name =
1706       fc_malloc(strlen(gfx_filename) + strlen(".")
1707                 + strlen(gfx_current_fileext) + 1);
1708 
1709     sprintf(full_name, "%s.%s", gfx_filename, gfx_current_fileext);
1710 
1711     real_full_name = fileinfoname(get_data_dirs(), full_name);
1712     free(full_name);
1713     if (real_full_name) {
1714       return fc_strdup(real_full_name);
1715     }
1716   }
1717 
1718   tileset_error(LOG_FATAL, _("Couldn't find a supported gfx file extension for \"%s\"."),
1719                 gfx_filename);
1720 
1721   return NULL;
1722 }
1723 
1724 /**********************************************************************
1725   Determine the sprite_type string.
1726 ***********************************************************************/
check_sprite_type(const char * sprite_type,const char * tile_section)1727 static int check_sprite_type(const char *sprite_type, const char *tile_section)
1728 {
1729   if (fc_strcasecmp(sprite_type, "corner") == 0) {
1730     return CELL_CORNER;
1731   }
1732   if (fc_strcasecmp(sprite_type, "single") == 0) {
1733     return CELL_WHOLE;
1734   }
1735   if (fc_strcasecmp(sprite_type, "whole") == 0) {
1736     return CELL_WHOLE;
1737   }
1738   log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1739   return CELL_WHOLE;
1740 }
1741 
1742 /**********************************************************************
1743   Finds and reads the toplevel tilespec file based on given name.
1744   Sets global variables, including tile sizes and full names for
1745   intro files.
1746   topology_id of -1 means any topology is acceptable.
1747 ***********************************************************************/
tileset_read_toplevel(const char * tileset_name,bool verbose,int topology_id,float scale)1748 struct tileset *tileset_read_toplevel(const char *tileset_name, bool verbose,
1749                                       int topology_id, float scale)
1750 {
1751   struct section_file *file;
1752   char *fname;
1753   const char *c;
1754   int i;
1755   size_t num_spec_files;
1756   const char **spec_filenames;
1757   size_t num_preferred_themes;
1758   struct section_list *sections = NULL;
1759   const char *file_capstr;
1760   bool duplicates_ok, is_hex;
1761   enum direction8 dir;
1762   struct tileset *t = NULL;
1763   const char *extraname;
1764   const char *tstr;
1765   int topo;
1766 
1767   fname = tilespec_fullname(tileset_name);
1768   if (!fname) {
1769     if (verbose) {
1770       log_error("Can't find tileset \"%s\".", tileset_name);
1771     }
1772     return NULL;
1773   }
1774   log_verbose("tilespec file is \"%s\".", fname);
1775 
1776   if (!(file = secfile_load(fname, TRUE))) {
1777     log_error("Could not open '%s':\n%s", fname, secfile_error());
1778     free(fname);
1779     return NULL;
1780   }
1781 
1782   if (!check_tilespec_capabilities(file, "tilespec",
1783                                    TILESPEC_CAPSTR, fname, verbose)) {
1784     secfile_destroy(file);
1785     free(fname);
1786     return NULL;
1787   }
1788 
1789   t = tileset_new();
1790   t->scale = scale;
1791   file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1792   duplicates_ok = (NULL != file_capstr
1793                    && has_capabilities("+duplicates_ok", file_capstr));
1794 
1795   tstr = secfile_lookup_str(file, "tilespec.name");
1796   /* Tileset name found */
1797   sz_strlcpy(t->given_name, tstr);
1798   tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1799   if (tstr[0] != '\0') {
1800     /* Tileset version found */
1801     sz_strlcpy(t->version, tstr);
1802   } else {
1803     /* No version information */
1804     t->version[0] = '\0';
1805   }
1806 
1807   tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
1808   if (tstr[0] != '\0') {
1809     int len;
1810 
1811     /* Tileset summary found */
1812     len = strlen(tstr);
1813     t->summary = fc_malloc(len + 1);
1814     fc_strlcpy(t->summary, tstr, len + 1);
1815   } else {
1816     /* No summary */
1817     if (t->summary != NULL) {
1818       free(t->summary);
1819       t->summary = NULL;
1820     }
1821   }
1822 
1823   tstr = secfile_lookup_str_default(file, "", "tilespec.description");
1824   if (tstr[0] != '\0') {
1825     int len;
1826 
1827     /* Tileset description found */
1828     len = strlen(tstr);
1829     t->description = fc_malloc(len + 1);
1830     fc_strlcpy(t->description, tstr, len + 1);
1831   } else {
1832     /* No description */
1833     if (t->description != NULL) {
1834       free(t->description);
1835       t->description = NULL;
1836     }
1837   }
1838 
1839   sz_strlcpy(t->name, tileset_name);
1840   if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1841       || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1842     log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1843     goto ON_ERROR;
1844   }
1845 
1846   tstr = secfile_lookup_str(file, "tilespec.type");
1847   if (tstr == NULL) {
1848     log_error("Tileset \"%s\": no tileset type", t->name);
1849     goto ON_ERROR;
1850   }
1851 
1852   t->type = ts_type_by_name(tstr, fc_strcasecmp);
1853   if (!ts_type_is_valid(t->type)) {
1854     log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1855     goto ON_ERROR;
1856   }
1857 
1858   if (t->type == TS_ISOMETRIC) {
1859     topo = TF_ISO;
1860   } else {
1861     topo = 0;
1862   }
1863 
1864   /* Read hex-tileset information. */
1865   t->hex_width = t->hex_height = 0;
1866   if (is_hex) {
1867     int hex_side;
1868 
1869     if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1870       log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1871       goto ON_ERROR;
1872     }
1873     hex_side = hex_side * t->scale;
1874     if (t->type == TS_ISOMETRIC) {
1875       t->hex_width = hex_side;
1876     } else {
1877       t->hex_height = hex_side;
1878     }
1879 
1880     topo |= TF_HEX;
1881 
1882     /* Hex tilesets are drawn the same as isometric. */
1883     /* FIXME: There will be other legal values to be used with hex
1884      * tileset in the future, and this would just overwrite it. */
1885     t->type = TS_ISOMETRIC;
1886   }
1887 
1888   if (topology_id >= 0 && topo != (topology_id & (TF_ISO | TF_HEX))) {
1889     /* Not of requested topology */
1890     goto ON_ERROR;
1891   }
1892 
1893   t->ts_topo_idx = ts_topology_index(topo);
1894 
1895   if (!is_view_supported(t->type)) {
1896     /* TRANS: "Overhead" or "Isometric" */
1897     log_normal(_("Client does not support %s tilesets."),
1898                _(ts_type_name(t->type)));
1899     log_normal(_("Using default tileset instead."));
1900     fc_assert(tileset_name != NULL);
1901     goto ON_ERROR;
1902   }
1903 
1904   /* Create arrays of valid and cardinal tileset dirs.  These depend
1905    * entirely on the tileset, not the topology.  They are also in clockwise
1906    * rotational ordering. */
1907   t->num_valid_tileset_dirs = t->num_cardinal_tileset_dirs = 0;
1908   dir = DIR8_NORTH;
1909   do {
1910     if (is_valid_tileset_dir(t, dir)) {
1911       t->valid_tileset_dirs[t->num_valid_tileset_dirs] = dir;
1912       t->num_valid_tileset_dirs++;
1913     }
1914     if (is_cardinal_tileset_dir(t, dir)) {
1915       t->cardinal_tileset_dirs[t->num_cardinal_tileset_dirs] = dir;
1916       t->num_cardinal_tileset_dirs++;
1917     }
1918 
1919     dir = dir_cw(dir);
1920   } while (dir != DIR8_NORTH);
1921   fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
1922   t->num_index_valid = 1 << t->num_valid_tileset_dirs;
1923   t->num_index_cardinal = 1 << t->num_cardinal_tileset_dirs;
1924 
1925   if (!secfile_lookup_int(file, &t->normal_tile_width,
1926                           "tilespec.normal_tile_width")
1927       || !secfile_lookup_int(file, &t->normal_tile_height,
1928                              "tilespec.normal_tile_height")) {
1929     log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1930     goto ON_ERROR;
1931   }
1932   t->normal_tile_width = ceil(t->scale * t->normal_tile_width);
1933   // Adjust width to be multiple of 8
1934   if (scale != 1.0f) {
1935     i = t->normal_tile_width;
1936     while (i % 8 != 0) {
1937       i++;
1938     }
1939     t->scale = (t->scale * i) / t->normal_tile_width;
1940     t->normal_tile_width = i;
1941   }
1942   t->normal_tile_height = ceil(t->scale * t->normal_tile_height);
1943   if (t->type == TS_ISOMETRIC) {
1944     t->full_tile_width = t->normal_tile_width;
1945     if (tileset_hex_height(t) > 0) {
1946       t->full_tile_height = t->normal_tile_height;
1947     } else {
1948       t->full_tile_height = 3 * t->normal_tile_height / 2;
1949     }
1950   } else {
1951     t->full_tile_width = t->normal_tile_width;
1952     t->full_tile_height = t->normal_tile_height;
1953   }
1954   t->unit_tile_width
1955     = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
1956   t->unit_tile_height
1957     = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
1958   if (!secfile_lookup_int(file, &t->small_sprite_width,
1959                           "tilespec.small_tile_width")
1960       || !secfile_lookup_int(file, &t->small_sprite_height,
1961                              "tilespec.small_tile_height")) {
1962     log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1963     goto ON_ERROR;
1964   }
1965   if (t->unit_tile_width != t->full_tile_width && t->scale != 1.0f) {
1966     t->unit_tile_width = ceil(t->unit_tile_width * t->scale);
1967   }
1968   if (t->unit_tile_height != t->full_tile_height && t->scale != 1.0f) {
1969     t->unit_tile_height = ceil(t->unit_tile_height * t->scale);
1970   }
1971   t->small_sprite_width = t->small_sprite_width * t->scale;
1972   t->small_sprite_height = t->small_sprite_height * t->scale;
1973   log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1974               t->normal_tile_width, t->normal_tile_height,
1975               t->full_tile_width, t->full_tile_height,
1976               t->small_sprite_width, t->small_sprite_height);
1977 
1978   tstr = secfile_lookup_str(file, "tilespec.fog_style");
1979   if (tstr == NULL) {
1980     log_error("Tileset \"%s\": no fog_style", t->name);
1981     goto ON_ERROR;
1982   }
1983 
1984   t->fogstyle = fog_style_by_name(tstr, fc_strcasecmp);
1985   if (!fog_style_is_valid(t->fogstyle)) {
1986     log_error("Tileset \"%s\": unknown fog_style \"%s\"", t->name, tstr);
1987     goto ON_ERROR;
1988   }
1989 
1990   tstr = secfile_lookup_str(file, "tilespec.darkness_style");
1991   if (tstr == NULL) {
1992     log_error("Tileset \"%s\": no darkness_style", t->name);
1993     goto ON_ERROR;
1994   }
1995 
1996   t->darkness_style = darkness_style_by_name(tstr, fc_strcasecmp);
1997   if (!darkness_style_is_valid(t->darkness_style)) {
1998     log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t->name, tstr);
1999     goto ON_ERROR;
2000   }
2001 
2002   if (t->darkness_style == DARKNESS_ISORECT
2003       && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
2004     log_error("Invalid darkness style set in tileset \"%s\".", t->name);
2005     goto ON_ERROR;
2006   }
2007   t->darkness_layer = secfile_lookup_int_default(file, 0, "tilespec.darkness_layer");
2008   if (t->darkness_layer < 0 || t->darkness_layer >= TERRAIN_LAYER_COUNT) {
2009     tileset_error(LOG_ERROR, "Invalid darkness layer %d in tileset \"%s\"",
2010                   t->darkness_layer, t->name);
2011     goto ON_ERROR;
2012   }
2013 
2014   if (!secfile_lookup_int(file, &t->unit_flag_offset_x,
2015                           "tilespec.unit_flag_offset_x")
2016       || !secfile_lookup_int(file, &t->unit_flag_offset_y,
2017                              "tilespec.unit_flag_offset_y")
2018       || !secfile_lookup_int(file, &t->city_flag_offset_x,
2019                              "tilespec.city_flag_offset_x")
2020       || !secfile_lookup_int(file, &t->city_flag_offset_y,
2021                              "tilespec.city_flag_offset_y")
2022       || !secfile_lookup_int(file, &t->unit_offset_x,
2023                              "tilespec.unit_offset_x")
2024       || !secfile_lookup_int(file, &t->unit_offset_y,
2025                              "tilespec.unit_offset_y")
2026       || !secfile_lookup_int(file, &t->activity_offset_x,
2027                              "tilespec.activity_offset_x")
2028       || !secfile_lookup_int(file, &t->activity_offset_y,
2029                              "tilespec.activity_offset_y")
2030       || !secfile_lookup_int(file, &t->city_offset_x,
2031                              "tilespec.city_offset_x")
2032       || !secfile_lookup_int(file, &t->city_offset_y,
2033                              "tilespec.city_offset_y")
2034       || !secfile_lookup_int(file, &t->citybar_offset_y,
2035                              "tilespec.citybar_offset_y")
2036       || !secfile_lookup_int(file, &t->tilelabel_offset_y,
2037                              "tilespec.tilelabel_offset_y")
2038       || !secfile_lookup_int(file, &t->occupied_offset_x,
2039                              "tilespec.occupied_offset_x")
2040       || !secfile_lookup_int(file, &t->occupied_offset_y,
2041                              "tilespec.occupied_offset_y")
2042       || !secfile_lookup_int(file, &t->city_names_font_size,
2043                              "tilespec.city_names_font_size")
2044       || !secfile_lookup_int(file, &t->city_productions_font_size,
2045                              "tilespec.city_productions_font_size")) {
2046     log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2047     goto ON_ERROR;
2048   }
2049 
2050   t->unit_upkeep_offset_y = secfile_lookup_int_default(file, tileset_tile_height(t),
2051                                                        "tilespec.unit_upkeep_offset_y");
2052   t->unit_upkeep_small_offset_y = secfile_lookup_int_default(file, t->unit_upkeep_offset_y,
2053                                                              "tilespec.unit_upkeep_small_offset_y");
2054   t->unit_flag_offset_x = t->scale * t->unit_flag_offset_x;
2055   t->unit_flag_offset_y = t->scale * t->unit_flag_offset_y;
2056   t->city_flag_offset_x = t->scale * t->city_flag_offset_x;
2057   t->city_flag_offset_y = t->scale * t->city_flag_offset_y;
2058   t->unit_offset_x = t->scale * t->unit_offset_x;
2059   t->unit_offset_y = t->scale * t->unit_offset_y;
2060   t->activity_offset_x = t->scale * t->activity_offset_x;
2061   t->activity_offset_y = t->scale * t->activity_offset_y;
2062   t->city_offset_x = t->scale * t->city_offset_x;
2063   t->city_offset_y = t->scale * t->city_offset_y;
2064   t->citybar_offset_y = t->scale * t->citybar_offset_y;
2065   t->tilelabel_offset_y = t->scale * t->tilelabel_offset_y;
2066   t->occupied_offset_x = t->scale * t->occupied_offset_x;
2067   t->occupied_offset_y = t->scale * t->occupied_offset_y;
2068   if (t->scale != 1.0f
2069       && t->unit_upkeep_offset_y != tileset_tile_height(t)) {
2070     t->unit_upkeep_offset_y = t->scale * t->unit_upkeep_offset_y;
2071   }
2072   if (t->scale != 1.0f
2073       && t->unit_upkeep_small_offset_y != t->unit_upkeep_offset_y) {
2074     t->unit_upkeep_small_offset_y = t->scale * t->unit_upkeep_small_offset_y;
2075   }
2076   /* Tell client, although many clients ignore this in favour of their
2077    * own configuration */
2078   set_city_names_font_sizes(t->city_names_font_size,
2079                             t->city_productions_font_size);
2080 
2081   c = secfile_lookup_str(file, "tilespec.main_intro_file");
2082   t->main_intro_filename = tilespec_gfx_filename(c);
2083   log_debug("intro file %s", t->main_intro_filename);
2084 
2085   c = secfile_lookup_str_default(file, NULL, "tilespec.minimap_intro_file");
2086   if (c == NULL) {
2087     t->minimap_intro_filename = NULL;
2088   } else {
2089     t->minimap_intro_filename = tilespec_gfx_filename(c);
2090     log_debug("radar file %s", t->minimap_intro_filename);
2091   }
2092 
2093   /* Terrain layer info. */
2094   for (i = 0; i < MAX_NUM_LAYERS; i++) {
2095     struct tileset_layer *tslp = &t->layers[i];
2096     int j, k;
2097 
2098     tslp->match_types =
2099         (char **) secfile_lookup_str_vec(file, &tslp->match_count,
2100                                          "layer%d.match_types", i);
2101     for (j = 0; j < tslp->match_count; j++) {
2102       tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
2103 
2104       for (k = 0; k < j; k++) {
2105         if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
2106           tileset_error(LOG_FATAL, _("[layer%d] match_types: \"%s\" initial "
2107                                      "('%c') is not unique."),
2108                         i, tslp->match_types[j], tslp->match_types[j][0]);
2109           /* FIXME: Returns NULL. */
2110         }
2111       }
2112     }
2113   }
2114 
2115   /* Tile drawing info. */
2116   sections = secfile_sections_by_name_prefix(file, TILE_SECTION_PREFIX);
2117   if (NULL == sections || 0 == section_list_size(sections)) {
2118     tileset_error(LOG_ERROR, _("No [%s] sections supported by tileset \"%s\"."),
2119                   TILE_SECTION_PREFIX, fname);
2120     goto ON_ERROR;
2121   }
2122 
2123   fc_assert(t->tile_hash == NULL);
2124   t->tile_hash = drawing_hash_new();
2125 
2126   section_list_iterate(sections, psection) {
2127     const char *sec_name = section_name(psection);
2128     struct drawing_data *draw = drawing_data_new();
2129     const char *sprite_type;
2130     int l;
2131     const char *terrain_name;
2132 
2133     terrain_name = secfile_lookup_str(file, "%s.tag", sec_name);
2134 
2135     if (terrain_name != NULL) {
2136       draw->name = fc_strdup(terrain_name);
2137     } else {
2138       tileset_error(LOG_ERROR, _("No terrain tag given in section [%s]."), sec_name);
2139       drawing_data_destroy(draw);
2140       goto ON_ERROR;
2141     }
2142 
2143     draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
2144                                                 sec_name);
2145     draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
2146 
2147     draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
2148                                                     "%s.is_reversed",
2149                                                     sec_name);
2150     draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
2151                                                   sec_name);
2152     draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
2153 
2154     for (l = 0; l < draw->num_layers; l++) {
2155       struct drawing_layer *dlp = &draw->layer[l];
2156       struct tileset_layer *tslp = &t->layers[l];
2157       const char *match_type;
2158       const char **match_with;
2159       size_t count;
2160 
2161       dlp->is_tall
2162         = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
2163                                       sec_name, l);
2164       dlp->offset_x
2165         = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
2166                                      sec_name, l);
2167       dlp->offset_y
2168         = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
2169                                      sec_name, l);
2170       dlp->offset_x = ceil(t->scale * dlp->offset_x);
2171       dlp->offset_y = ceil(t->scale * dlp->offset_y);
2172 
2173       match_type = secfile_lookup_str_default(file, NULL,
2174                                               "%s.layer%d_match_type",
2175                                               sec_name, l);
2176       if (match_type) {
2177         int j;
2178 
2179         /* Determine our match_type. */
2180         for (j = 0; j < tslp->match_count; j++) {
2181           if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
2182             break;
2183           }
2184         }
2185         if (j >= tslp->match_count) {
2186           log_error("[%s] invalid match_type \"%s\".", sec_name, match_type);
2187         } else {
2188           dlp->match_index[dlp->match_indices++] = j;
2189         }
2190       }
2191 
2192       match_with = secfile_lookup_str_vec(file, &count,
2193                                           "%s.layer%d_match_with",
2194                                           sec_name, l);
2195       if (match_with) {
2196         int j, k;
2197 
2198         if (count > MAX_NUM_MATCH_WITH) {
2199           log_error("[%s] match_with has too many types (%d, max %d)",
2200                     sec_name, (int) count, MAX_NUM_MATCH_WITH);
2201           count = MAX_NUM_MATCH_WITH;
2202         }
2203 
2204         if (1 < dlp->match_indices) {
2205           log_error("[%s] previous match_with ignored.", sec_name);
2206           dlp->match_indices = 1;
2207         } else if (1 > dlp->match_indices) {
2208           log_error("[%s] missing match_type, using \"%s\".",
2209                     sec_name, tslp->match_types[0]);
2210           dlp->match_index[0] = 0;
2211           dlp->match_indices = 1;
2212         }
2213 
2214         for (k = 0; k < count; k++) {
2215           for (j = 0; j < tslp->match_count; j++) {
2216             if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
2217               break;
2218             }
2219           }
2220           if (j >= tslp->match_count) {
2221             log_error("[%s] layer%d_match_with: invalid  \"%s\".",
2222                       sec_name, l, match_with[k]);
2223           } else if (1 < count) {
2224             int m;
2225 
2226             for (m = 0; m < dlp->match_indices; m++) {
2227               if (dlp->match_index[m] == j) {
2228                 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
2229                           sec_name, l, match_with[k]);
2230                 break;
2231               }
2232             }
2233             if (m >= dlp->match_indices) {
2234               dlp->match_index[dlp->match_indices++] = j;
2235             }
2236           } else {
2237             dlp->match_index[dlp->match_indices++] = j;
2238           }
2239         }
2240         free(match_with);
2241         match_with = NULL;
2242       }
2243 
2244       /* Check match_indices */
2245       switch (dlp->match_indices) {
2246       case 0:
2247       case 1:
2248         dlp->match_style = MATCH_NONE;
2249         break;
2250       case 2:
2251         if (dlp->match_index[0] == dlp->match_index[1] ) {
2252           dlp->match_style = MATCH_SAME;
2253         } else {
2254           dlp->match_style = MATCH_PAIR;
2255         }
2256         break;
2257       default:
2258         dlp->match_style = MATCH_FULL;
2259         break;
2260       };
2261 
2262       sprite_type
2263 	= secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
2264                                      sec_name, l);
2265       dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
2266 
2267       switch (dlp->sprite_type) {
2268       case CELL_WHOLE:
2269 	/* OK, no problem */
2270 	break;
2271       case CELL_CORNER:
2272 	if (dlp->is_tall
2273 	    || dlp->offset_x > 0
2274 	    || dlp->offset_y > 0) {
2275           log_error("[%s] layer %d: you cannot have tall terrain or\n"
2276                     "a sprite offset with a cell-based drawing method.",
2277                     sec_name, l);
2278 	  dlp->is_tall = FALSE;
2279 	  dlp->offset_x = dlp->offset_y = 0;
2280 	}
2281 	break;
2282       };
2283     }
2284 
2285     if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
2286       log_error("warning: multiple tile sections containing terrain tag \"%s\".",
2287                 draw->name);
2288       goto ON_ERROR;
2289     }
2290   } section_list_iterate_end;
2291   section_list_destroy(sections);
2292   sections = NULL;
2293 
2294   t->estyle_hash = estyle_hash_new();
2295 
2296   for (i = 0; i < ESTYLE_COUNT; i++) {
2297     t->style_lists[i] = extra_type_list_new();
2298   }
2299   t->flagged_bases_list = extra_type_list_new();
2300 
2301   for (i = 0; (extraname = secfile_lookup_str_default(file, NULL,
2302                                                       "extras.styles%d.name",
2303                                                       i)); i++) {
2304     const char *style_name;
2305     enum extrastyle_id style;
2306 
2307     style_name = secfile_lookup_str_default(file, "Single1",
2308                                             "extras.styles%d.style", i);
2309     style = extrastyle_id_by_name(style_name, fc_strcasecmp);
2310     if (!extrastyle_id_is_valid(style)) {
2311       log_error("Unknown extra style \"%s\" for road \"%s\"",
2312                 style_name, extraname);
2313       goto ON_ERROR;
2314     }
2315 
2316     if (!estyle_hash_insert(t->estyle_hash, extraname, style)) {
2317       log_error("warning: duplicate extrastyle entry [%s].", extraname);
2318       goto ON_ERROR;
2319     }
2320   }
2321 
2322   spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
2323                                           "tilespec.files");
2324   if (NULL == spec_filenames || 0 == num_spec_files) {
2325     log_error("No tile graphics files specified in \"%s\"", fname);
2326     goto ON_ERROR;
2327   }
2328 
2329   fc_assert(t->sprite_hash == NULL);
2330   t->sprite_hash = sprite_hash_new();
2331   for (i = 0; i < num_spec_files; i++) {
2332     struct specfile *sf = fc_malloc(sizeof(*sf));
2333     const char *dname;
2334 
2335     log_debug("spec file %s", spec_filenames[i]);
2336 
2337     sf->big_sprite = NULL;
2338     dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
2339     if (!dname) {
2340       if (verbose) {
2341         log_error("Can't find spec file \"%s\".", spec_filenames[i]);
2342       }
2343       goto ON_ERROR;
2344     }
2345     sf->file_name = fc_strdup(dname);
2346     scan_specfile(t, sf, duplicates_ok);
2347 
2348     specfile_list_prepend(t->specfiles, sf);
2349   }
2350   free(spec_filenames);
2351 
2352   t->color_system = color_system_read(file);
2353 
2354   /* FIXME: remove this hack. */
2355   t->preferred_themes =
2356     (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2357                                      "tilespec.preferred_themes");
2358   if (num_preferred_themes <= 0) {
2359     t->preferred_themes =
2360       (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2361                                        "tilespec.prefered_themes");
2362     if (num_preferred_themes > 0) {
2363       log_deprecation("Entry tilespec.prefered_themes in tilespec."
2364                       " Use correct spelling tilespec.preferred_themes instead");
2365     }
2366   }
2367   t->num_preferred_themes = num_preferred_themes;
2368   for (i = 0; i < t->num_preferred_themes; i++) {
2369     t->preferred_themes[i] = fc_strdup(t->preferred_themes[i]);
2370   }
2371 
2372   secfile_check_unused(file);
2373   secfile_destroy(file);
2374   log_verbose("finished reading \"%s\".", fname);
2375   free(fname);
2376 
2377   return t;
2378 
2379 ON_ERROR:
2380   secfile_destroy(file);
2381   free(fname);
2382   tileset_free(t);
2383   if (NULL != sections) {
2384     section_list_destroy(sections);
2385   }
2386   return NULL;
2387 }
2388 
2389 /**********************************************************************
2390   Returns a text name for the citizen, as used in the tileset.
2391 ***********************************************************************/
citizen_rule_name(enum citizen_category citizen)2392 static const char *citizen_rule_name(enum citizen_category citizen)
2393 {
2394   /* These strings are used in reading the tileset.  Do not
2395    * translate. */
2396   switch (citizen) {
2397   case CITIZEN_HAPPY:
2398     return "happy";
2399   case CITIZEN_CONTENT:
2400     return "content";
2401   case CITIZEN_UNHAPPY:
2402     return "unhappy";
2403   case CITIZEN_ANGRY:
2404     return "angry";
2405   default:
2406     break;
2407   }
2408   log_error("Unknown citizen type: %d.", (int) citizen);
2409   return NULL;
2410 }
2411 
2412 /****************************************************************************
2413   Return a directional string for the cardinal directions.  Normally the
2414   binary value 1000 will be converted into "n1e0s0w0".  This is in a
2415   clockwise ordering.
2416 ****************************************************************************/
cardinal_index_str(const struct tileset * t,int idx)2417 static const char *cardinal_index_str(const struct tileset *t, int idx)
2418 {
2419   static char c[64];
2420   int i;
2421 
2422   c[0] = '\0';
2423   for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2424     int value = (idx >> i) & 1;
2425 
2426     cat_snprintf(c, sizeof(c), "%s%d",
2427                  dir_get_tileset_name(t->cardinal_tileset_dirs[i]), value);
2428   }
2429 
2430   return c;
2431 }
2432 
2433 /****************************************************************************
2434   Do the same thing as cardinal_str, except including all valid directions.
2435   The returned string is a pointer to static memory.
2436 ****************************************************************************/
valid_index_str(const struct tileset * t,int idx)2437 static char *valid_index_str(const struct tileset *t, int idx)
2438 {
2439   static char c[64];
2440   int i;
2441 
2442   c[0] = '\0';
2443   for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2444     int value = (idx >> i) & 1;
2445 
2446     cat_snprintf(c, sizeof(c), "%s%d",
2447 		 dir_get_tileset_name(t->valid_tileset_dirs[i]), value);
2448   }
2449 
2450   return c;
2451 }
2452 
2453 /**************************************************************************
2454   Loads the sprite. If the sprite is already loaded a reference
2455   counter is increased. Can return NULL if the sprite couldn't be
2456   loaded.
2457   Scale means if sprite should be scaled, smooth if scaling might use
2458   other scaling algorithm than nearest neighbor.
2459 **************************************************************************/
load_sprite(struct tileset * t,const char * tag_name,bool scale,bool smooth)2460 static struct sprite *load_sprite(struct tileset *t, const char *tag_name,
2461                                   bool scale, bool smooth)
2462 {
2463   struct small_sprite *ss;
2464   float sprite_scale = 1.0f;
2465 
2466   log_debug("load_sprite(tag='%s')", tag_name);
2467   /* Lookup information about where the sprite is found. */
2468   if (!sprite_hash_lookup(t->sprite_hash, tag_name, &ss)) {
2469     return NULL;
2470   }
2471 
2472   fc_assert(ss->ref_count >= 0);
2473 
2474   if (!ss->sprite) {
2475     /* If the sprite hasn't been loaded already, then load it. */
2476     fc_assert(ss->ref_count == 0);
2477     if (ss->file) {
2478       int w, h;
2479       struct sprite *s;
2480 
2481       if (scale) {
2482         s = load_gfx_file(ss->file);
2483         get_sprite_dimensions(s, &w, &h);
2484         ss->sprite = crop_sprite(s, 0, 0, w,
2485                                  h, NULL, -1, -1, t->scale, smooth);
2486         free_sprite(s);
2487       } else {
2488         ss->sprite = load_gfx_file(ss->file);
2489       }
2490       if (!ss->sprite) {
2491         tileset_error(LOG_FATAL, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2492                       ss->file, tag_name);
2493       }
2494     } else {
2495       int sf_w, sf_h;
2496 
2497       ensure_big_sprite(ss->sf);
2498       get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2499       if (ss->x < 0 || ss->x + ss->width > sf_w
2500 	  || ss->y < 0 || ss->y + ss->height > sf_h) {
2501         tileset_error(LOG_ERROR, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2502                       tag_name, ss->sf->file_name);
2503 	return NULL;
2504       }
2505       if (scale) {
2506         sprite_scale = t->scale;
2507       }
2508       ss->sprite = crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width,
2509                                ss->height, NULL, -1, -1, sprite_scale,
2510                                smooth);
2511     }
2512   }
2513 
2514   /* Track the reference count so we know when to free the sprite. */
2515   ss->ref_count++;
2516 
2517   return ss->sprite;
2518 }
2519 
2520 /**************************************************************************
2521   Create a sprite with the given color and tag.
2522 **************************************************************************/
create_plr_sprite(struct color * pcolor)2523 static struct sprite *create_plr_sprite(struct color *pcolor)
2524 {
2525   struct sprite *sprite;
2526 
2527   fc_assert_ret_val(pcolor != NULL, NULL);
2528 
2529   if (tileset->scale == 1.0f) {
2530     sprite = create_sprite(128, 64, pcolor);
2531   } else {
2532     sprite = create_sprite(tileset->full_tile_width,
2533                            tileset->full_tile_height, pcolor);
2534   }
2535 
2536   return sprite;
2537 }
2538 
2539 /**************************************************************************
2540   Unloads the sprite. Decrease the reference counter. If the last
2541   reference is removed the sprite is freed.
2542 **************************************************************************/
unload_sprite(struct tileset * t,const char * tag_name)2543 static void unload_sprite(struct tileset *t, const char *tag_name)
2544 {
2545   struct small_sprite *ss;
2546 
2547   sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
2548   fc_assert_ret(ss);
2549   fc_assert_ret(ss->ref_count >= 1);
2550   fc_assert_ret(ss->sprite);
2551 
2552   ss->ref_count--;
2553 
2554   if (ss->ref_count == 0) {
2555     /* Nobody's using the sprite anymore, so we should free it.  We know
2556      * where to find it if we need it again. */
2557     log_debug("freeing sprite '%s'.", tag_name);
2558     free_sprite(ss->sprite);
2559     ss->sprite = NULL;
2560   }
2561 }
2562 
2563 /**************************************************************************
2564   Return TRUE iff the specified sprite exists in the tileset (whether
2565   or not it is currently loaded).
2566 **************************************************************************/
sprite_exists(const struct tileset * t,const char * tag_name)2567 static bool sprite_exists(const struct tileset *t, const char *tag_name)
2568 {
2569   /* Lookup information about where the sprite is found. */
2570   return sprite_hash_lookup(t->sprite_hash, tag_name, NULL);
2571 }
2572 
2573 /* Not very safe, but convenient: */
2574 #define SET_SPRITE(field, tag)					  \
2575   do {								  \
2576     t->sprites.field = load_sprite(t, tag, TRUE, TRUE);			  \
2577     if (t->sprites.field == NULL) {                               \
2578       tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag);    \
2579     }                                                             \
2580   } while(FALSE)
2581 
2582 #define SET_SPRITE_NOTSMOOTH(field, tag)					  \
2583   do {								  \
2584     t->sprites.field = load_sprite(t, tag, TRUE, FALSE);			  \
2585     if (t->sprites.field == NULL) {                               \
2586       tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag);    \
2587     }                                                             \
2588   } while(FALSE)
2589 
2590 #define SET_SPRITE_UNSCALED(field, tag)           \
2591   do {                  \
2592     t->sprites.field = load_sprite(t, tag, FALSE, FALSE);       \
2593     if (t->sprites.field == NULL) {                               \
2594       tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag);    \
2595     }                                                             \
2596   } while(FALSE)
2597 
2598 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2599 #define SET_SPRITE_ALT(field, tag, alt)					    \
2600   do {									    \
2601     t->sprites.field = load_sprite(t, tag, TRUE, TRUE);			    \
2602     if (!t->sprites.field) {						    \
2603       t->sprites.field = load_sprite(t, alt, TRUE, TRUE);			    \
2604     }									    \
2605     if (t->sprites.field == NULL) {                                         \
2606       tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are "  \
2607                                  "both missing."), tag, alt);               \
2608     }                                                                       \
2609   } while(FALSE)
2610 
2611 /* Sets sprites.field to tag, or NULL if not available */
2612 #define SET_SPRITE_OPT(field, tag) \
2613   t->sprites.field = load_sprite(t, tag, TRUE, TRUE)
2614 
2615 #define SET_SPRITE_ALT_OPT(field, tag, alt)				    \
2616   do {									    \
2617     t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2618 						   "sprite", #field, TRUE);	    \
2619   } while (FALSE)
2620 
2621 /****************************************************************************
2622   Setup the graphics for specialist types.
2623 ****************************************************************************/
tileset_setup_specialist_type(struct tileset * t,Specialist_type_id id)2624 void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
2625 {
2626   /* Load the specialist sprite graphics. */
2627   char buffer[512];
2628   int j;
2629   const char *name = specialist_rule_name(specialist_by_number(id));
2630   const char *graphic_alt = specialist_by_number(id)->graphic_alt;
2631 
2632   for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2633     /* Try rule name + index number */
2634     fc_snprintf(buffer, sizeof(buffer), "specialist.%s_%d", name, j);
2635     t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer, FALSE,
2636                                                       FALSE);
2637 
2638     /* Break if no more index specific sprites are defined */
2639     if (!t->sprites.specialist[id].sprite[j]) {
2640       break;
2641     }
2642   }
2643 
2644   /* Nothing? Try the alt tag */
2645   if (j == 0) {
2646     t->sprites.specialist[id].sprite[j] = load_sprite(t, graphic_alt, FALSE,
2647                                                       FALSE);
2648 
2649     if (t->sprites.specialist[id].sprite[j]) {
2650       j = 1;
2651     }
2652   }
2653 
2654   t->sprites.specialist[id].count = j;
2655 
2656   /* Still nothing? Give up. */
2657   if (j == 0) {
2658     tileset_error(LOG_FATAL, _("No graphics for specialist \"%s\"."), name);
2659   }
2660 }
2661 
2662 /****************************************************************************
2663   Setup the graphics for (non-specialist) citizen types.
2664 ****************************************************************************/
tileset_setup_citizen_types(struct tileset * t)2665 static void tileset_setup_citizen_types(struct tileset *t)
2666 {
2667   int i, j;
2668   char buffer[512];
2669 
2670   /* Load the citizen sprite graphics, no specialist. */
2671   for (i = 0; i < CITIZEN_LAST; i++) {
2672     const char *name = citizen_rule_name(i);
2673 
2674     for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2675       fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
2676       t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer, FALSE, FALSE);
2677       if (!t->sprites.citizen[i].sprite[j]) {
2678 	break;
2679       }
2680     }
2681     t->sprites.citizen[i].count = j;
2682     if (j == 0) {
2683       tileset_error(LOG_FATAL, _("No graphics for citizen \"%s\"."), name);
2684     }
2685   }
2686 }
2687 
2688 /****************************************************************************
2689   Return the sprite in the city_sprite listing that corresponds to this
2690   city - based on city style and size.
2691 
2692   See also load_city_sprite, free_city_sprite.
2693 ****************************************************************************/
get_city_sprite(const struct city_sprite * city_sprite,const struct city * pcity)2694 static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
2695 				      const struct city *pcity)
2696 {
2697   /* get style and match the best tile based on city size */
2698   int style = style_of_city(pcity);
2699   int num_thresholds;
2700   struct city_style_threshold *thresholds;
2701   int img_index;
2702 
2703   fc_assert_ret_val(style < city_sprite->num_styles, NULL);
2704 
2705   num_thresholds = city_sprite->styles[style].land_num_thresholds;
2706   thresholds = city_sprite->styles[style].land_thresholds;
2707 
2708   if (num_thresholds == 0) {
2709     return NULL;
2710   }
2711 
2712   /* Get the sprite with the index defined by the effects. */
2713   img_index = pcity->client.city_image;
2714   if (img_index == -100) {
2715     /* Server doesn't know right value as this is from old savegame.
2716      * Guess here based on *client* side information as was done in
2717      * versions where information was not saved to savegame - this should
2718      * give us right answer of what city looked like by the time it was
2719      * put under FoW. */
2720     img_index = get_city_bonus(pcity, EFT_CITY_IMAGE);
2721   }
2722   img_index = CLIP(0, img_index, num_thresholds - 1);
2723 
2724   return thresholds[img_index].sprite;
2725 }
2726 
2727 /****************************************************************************
2728   Allocates one threshold set for city sprite
2729 ****************************************************************************/
load_city_thresholds_sprites(struct tileset * t,const char * tag,char * graphic,char * graphic_alt,struct city_style_threshold ** thresholds)2730 static int load_city_thresholds_sprites(struct tileset *t, const char *tag,
2731                                         char *graphic, char *graphic_alt,
2732                                         struct city_style_threshold **thresholds)
2733 {
2734   char buffer[128];
2735   char *gfx_in_use = graphic;
2736   int num_thresholds = 0;
2737   struct sprite *sprite;
2738   int size;
2739 
2740   *thresholds = NULL;
2741 
2742   for (size = 0; size < MAX_CITY_SIZE; size++) {
2743     fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
2744                 gfx_in_use, tag, size);
2745     if ((sprite = load_sprite(t, buffer, TRUE, TRUE))) {
2746       num_thresholds++;
2747       *thresholds = fc_realloc(*thresholds, num_thresholds * sizeof(**thresholds));
2748       (*thresholds)[num_thresholds - 1].sprite = sprite;
2749     } else if (size == 0) {
2750       if (gfx_in_use == graphic) {
2751         /* Try again with graphic_alt. */
2752         size--;
2753         gfx_in_use = graphic_alt;
2754       } else {
2755         /* Don't load any others if the 0 element isn't there. */
2756         break;
2757       }
2758     }
2759   }
2760 
2761   return num_thresholds;
2762 }
2763 
2764 /****************************************************************************
2765   Allocates and loads a new city sprite from the given sprite tags.
2766 
2767   tag may be NULL.
2768 
2769   See also get_city_sprite, free_city_sprite.
2770 ****************************************************************************/
load_city_sprite(struct tileset * t,const char * tag)2771 static struct city_sprite *load_city_sprite(struct tileset *t,
2772 					    const char *tag)
2773 {
2774   struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
2775   int style;
2776 
2777   /* Store number of styles we have allocated memory for.
2778    * game.control.styles_count might change if client disconnects from
2779    * server and connects new one. */
2780   city_sprite->num_styles = game.control.styles_count;
2781   city_sprite->styles = fc_malloc(city_sprite->num_styles
2782 				  * sizeof(*city_sprite->styles));
2783 
2784   for (style = 0; style < city_sprite->num_styles; style++) {
2785     city_sprite->styles[style].land_num_thresholds =
2786       load_city_thresholds_sprites(t, tag, city_styles[style].graphic,
2787                                    city_styles[style].graphic_alt,
2788                                    &city_sprite->styles[style].land_thresholds);
2789   }
2790 
2791   return city_sprite;
2792 }
2793 
2794 /****************************************************************************
2795   Frees a city sprite.
2796 
2797   See also get_city_sprite, load_city_sprite.
2798 ****************************************************************************/
free_city_sprite(struct city_sprite * city_sprite)2799 static void free_city_sprite(struct city_sprite *city_sprite)
2800 {
2801   int style;
2802 
2803   if (!city_sprite) {
2804     return;
2805   }
2806   for (style = 0; style < city_sprite->num_styles; style++) {
2807     if (city_sprite->styles[style].land_thresholds) {
2808       free(city_sprite->styles[style].land_thresholds);
2809     }
2810   }
2811   free(city_sprite->styles);
2812   free(city_sprite);
2813 }
2814 
2815 /**********************************************************************
2816   Initialize 'sprites' structure based on hardwired tags which
2817   freeciv always requires.
2818 ***********************************************************************/
tileset_lookup_sprite_tags(struct tileset * t)2819 static void tileset_lookup_sprite_tags(struct tileset *t)
2820 {
2821   char buffer[512], buffer2[512];
2822   const int W = t->normal_tile_width, H = t->normal_tile_height;
2823   int i, j, f;
2824 
2825   fc_assert_ret(t->sprite_hash != NULL);
2826 
2827   SET_SPRITE_UNSCALED(treaty_thumb[0], "treaty.disagree_thumb_down");
2828   SET_SPRITE_UNSCALED(treaty_thumb[1], "treaty.agree_thumb_up");
2829 
2830   for (j = 0; j < INDICATOR_COUNT; j++) {
2831     const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2832 
2833     for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2834       fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
2835       SET_SPRITE_UNSCALED(indicator[j][i], buffer);
2836     }
2837   }
2838 
2839   SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
2840   SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
2841   SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
2842   if (t->type == TS_ISOMETRIC) {
2843     SET_SPRITE(dither_tile, "t.dither_tile");
2844   }
2845 
2846   if (tileset_is_isometric(tileset)) {
2847     SET_SPRITE_NOTSMOOTH(mask.tile, "mask.tile");
2848   } else {
2849     SET_SPRITE(mask.tile, "mask.tile");
2850   }
2851   SET_SPRITE(mask.worked_tile, "mask.worked_tile");
2852   SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
2853 
2854   SET_SPRITE_UNSCALED(tax_luxury, "s.tax_luxury");
2855   SET_SPRITE_UNSCALED(tax_science, "s.tax_science");
2856   SET_SPRITE_UNSCALED(tax_gold, "s.tax_gold");
2857 
2858   tileset_setup_citizen_types(t);
2859 
2860   for (i = 0; i < SPACESHIP_COUNT; i++) {
2861     const char *names[SPACESHIP_COUNT]
2862       = {"solar_panels", "life_support", "habitation",
2863 	 "structural", "fuel", "propulsion", "exhaust"};
2864 
2865     fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
2866     SET_SPRITE(spaceship[i], buffer);
2867   }
2868 
2869   for (i = 0; i < CURSOR_LAST; i++) {
2870     for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2871       const char *names[CURSOR_LAST] =
2872                {"goto", "patrol", "paradrop", "nuke", "select",
2873 		"invalid", "attack", "edit_paint", "edit_add", "wait"};
2874       struct small_sprite *ss;
2875 
2876       fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2877       fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
2878       SET_SPRITE(cursor[i].frame[f], buffer);
2879       if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
2880         t->sprites.cursor[i].hot_x = ss->hot_x;
2881         t->sprites.cursor[i].hot_y = ss->hot_y;
2882       }
2883     }
2884   }
2885 
2886   for (i = 0; i < ICON_COUNT; i++) {
2887     const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
2888 
2889     fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
2890     SET_SPRITE(icon[i], buffer);
2891   }
2892 
2893   for (i = 0; i < E_COUNT; i++) {
2894     const char *tag = get_event_tag(i);
2895 
2896     SET_SPRITE(events[i], tag);
2897   }
2898 
2899   SET_SPRITE(explode.nuke, "explode.nuke");
2900 
2901   sprite_vector_init(&t->sprites.explode.unit);
2902   for (i = 0; ; i++) {
2903     struct sprite *sprite;
2904 
2905     fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
2906     sprite = load_sprite(t, buffer, TRUE, TRUE);
2907     if (!sprite) {
2908       break;
2909     }
2910     sprite_vector_append(&t->sprites.explode.unit, sprite);
2911   }
2912 
2913   SET_SPRITE(unit.auto_attack,  "unit.auto_attack");
2914   SET_SPRITE(unit.auto_settler, "unit.auto_settler");
2915   SET_SPRITE(unit.auto_explore, "unit.auto_explore");
2916   SET_SPRITE(unit.fortified,	"unit.fortified");
2917   SET_SPRITE(unit.fortifying,	"unit.fortifying");
2918   SET_SPRITE(unit.go_to,	"unit.goto");
2919   SET_SPRITE(unit.irrigate,     "unit.irrigate");
2920   SET_SPRITE(unit.plant,        "unit.plant");
2921   SET_SPRITE(unit.pillage,	"unit.pillage");
2922   SET_SPRITE(unit.sentry,	"unit.sentry");
2923   SET_SPRITE(unit.convert,      "unit.convert");
2924   SET_SPRITE(unit.stack,	"unit.stack");
2925   SET_SPRITE(unit.loaded,       "unit.loaded");
2926   SET_SPRITE(unit.transform,    "unit.transform");
2927   SET_SPRITE(unit.connect,      "unit.connect");
2928   SET_SPRITE(unit.patrol,       "unit.patrol");
2929   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
2930     fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
2931     fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
2932     fc_assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
2933     SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
2934   }
2935   SET_SPRITE(unit.lowfuel, "unit.lowfuel");
2936   SET_SPRITE(unit.tired, "unit.tired");
2937 
2938   for(i=0; i<NUM_TILES_HP_BAR; i++) {
2939     fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
2940     SET_SPRITE(unit.hp_bar[i], buffer);
2941   }
2942 
2943   for (i = 0; i < MAX_VET_LEVELS; i++) {
2944     /* Veteran level sprites are optional.  For instance "green" units
2945      * usually have no special graphic. */
2946     fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
2947     t->sprites.unit.vet_lev[i] = load_sprite(t, buffer, TRUE, TRUE);
2948   }
2949 
2950   t->sprites.unit.select[0] = NULL;
2951   if (sprite_exists(t, "unit.select0")) {
2952     for (i = 0; i < NUM_TILES_SELECT; i++) {
2953       fc_snprintf(buffer, sizeof(buffer), "unit.select%d", i);
2954       SET_SPRITE(unit.select[i], buffer);
2955     }
2956   }
2957 
2958   SET_SPRITE(citybar.shields, "citybar.shields");
2959   SET_SPRITE(citybar.food, "citybar.food");
2960   SET_SPRITE(citybar.trade, "citybar.trade");
2961   SET_SPRITE(citybar.occupied, "citybar.occupied");
2962   SET_SPRITE(citybar.background, "citybar.background");
2963   sprite_vector_init(&t->sprites.citybar.occupancy);
2964   for (i = 0; ; i++) {
2965     struct sprite *sprite;
2966 
2967     fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
2968     sprite = load_sprite(t, buffer, TRUE, TRUE);
2969     if (!sprite) {
2970       break;
2971     }
2972     sprite_vector_append(&t->sprites.citybar.occupancy, sprite);
2973   }
2974   if (t->sprites.citybar.occupancy.size < 2) {
2975     tileset_error(LOG_FATAL, _("Missing necessary citybar.occupancy_N sprites."));
2976   }
2977 
2978 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2979   SET_EDITOR_SPRITE(erase);
2980   SET_EDITOR_SPRITE(brush);
2981   SET_EDITOR_SPRITE(copy);
2982   SET_EDITOR_SPRITE(paste);
2983   SET_EDITOR_SPRITE(copypaste);
2984   SET_EDITOR_SPRITE(startpos);
2985   SET_EDITOR_SPRITE(terrain);
2986   SET_EDITOR_SPRITE(terrain_resource);
2987   SET_EDITOR_SPRITE(terrain_special);
2988   SET_EDITOR_SPRITE(unit);
2989   SET_EDITOR_SPRITE(city);
2990   SET_EDITOR_SPRITE(vision);
2991   SET_EDITOR_SPRITE(territory);
2992   SET_EDITOR_SPRITE(properties);
2993   SET_EDITOR_SPRITE(road);
2994   SET_EDITOR_SPRITE(military_base);
2995 #undef SET_EDITOR_SPRITE
2996 
2997   SET_SPRITE(city.disorder, "city.disorder");
2998 
2999   /* Fallbacks for goto path turn numbers:
3000    *   path.step_%d, path.exhausted_mp_%d
3001    *   --> path.turns_%d
3002    *       --> city.size_%d */
3003 #define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name)        \
3004   fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
3005   SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer);           \
3006   if (t->sprites.path.s[state].turns ## factor_name [i] == NULL) {          \
3007     t->sprites.path.s[state].turns ## factor_name [i] =                     \
3008         t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i];            \
3009   }
3010   for(i=0; i<NUM_TILES_DIGITS; i++) {
3011     fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
3012     SET_SPRITE(city.size[i], buffer);
3013     fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
3014     SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns[i], buffer2, buffer);
3015     SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step",,);
3016     SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp",,);
3017 
3018     fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
3019     SET_SPRITE(city.size_tens[i], buffer);
3020     fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
3021     SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns_tens[i], buffer2, buffer);
3022     SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 0, _tens);
3023     SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 0, _tens);
3024 
3025     fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
3026     SET_SPRITE_OPT(city.size_hundreds[i], buffer);
3027     fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
3028     SET_SPRITE_ALT_OPT(path.s[GTS_MP_LEFT].turns_hundreds[i], buffer2,
3029                        buffer);
3030     SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 00, _hundreds);
3031     SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 00, _hundreds);
3032 
3033     fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
3034     SET_SPRITE(city.tile_foodnum[i], buffer);
3035     fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
3036     SET_SPRITE(city.tile_shieldnum[i], buffer);
3037     fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
3038     SET_SPRITE(city.tile_tradenum[i], buffer);
3039   }
3040 #undef SET_GOTO_TURN_SPRITE
3041 
3042   /* Must have at least one upkeep sprite per output type (and unhappy) */
3043   /* The rest are optional; we copy the previous sprite for unspecified ones */
3044   fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
3045   SET_SPRITE(upkeep.unhappy[0], buffer);
3046   for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
3047     fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
3048     if (sprite_exists(t, buffer2)) {
3049       SET_SPRITE(upkeep.unhappy[i], buffer2);
3050       fc_strlcpy(buffer, buffer2, sizeof(buffer));
3051     } else {
3052       SET_SPRITE(upkeep.unhappy[i], buffer);
3053     }
3054   }
3055   output_type_iterate(o) {
3056     fc_snprintf(buffer, sizeof(buffer),
3057                 "upkeep.%s", get_output_identifier(o));
3058     SET_SPRITE_OPT(upkeep.output[o][0], buffer);
3059     for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
3060       fc_snprintf(buffer2, sizeof(buffer2),
3061                   "upkeep.%s%d", get_output_identifier(o), i+1);
3062       if (sprite_exists(t, buffer2)) {
3063         SET_SPRITE(upkeep.output[o][i], buffer2);
3064         fc_strlcpy(buffer, buffer2, sizeof(buffer));
3065       } else {
3066         /* Optional, as maybe the upkeep 1 sprite didn't exist either */
3067         SET_SPRITE_OPT(upkeep.output[o][i], buffer);
3068       }
3069     }
3070   } output_type_iterate_end;
3071 
3072   t->max_upkeep_height = calculate_max_upkeep_height(t);
3073 
3074   SET_SPRITE(user.attention, "user.attention");
3075 
3076   SET_SPRITE_OPT(path.s[GTS_MP_LEFT].specific, "path.normal");
3077   SET_SPRITE_OPT(path.s[GTS_EXHAUSTED_MP].specific, "path.exhausted_mp");
3078   SET_SPRITE_OPT(path.s[GTS_TURN_STEP].specific, "path.step");
3079   SET_SPRITE(path.waypoint, "path.waypoint");
3080 
3081   SET_SPRITE_NOTSMOOTH(tx.fog, "tx.fog");
3082 
3083   sprite_vector_init(&t->sprites.colors.overlays);
3084   for (i = 0; ; i++) {
3085     struct sprite *sprite;
3086 
3087     fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
3088     sprite = load_sprite(t, buffer, TRUE, TRUE);
3089     if (!sprite) {
3090       break;
3091     }
3092     sprite_vector_append(&t->sprites.colors.overlays, sprite);
3093   }
3094   if (i == 0) {
3095     tileset_error(LOG_FATAL, _("Missing overlay-color sprite colors.overlay_0."));
3096   }
3097 
3098   /* Chop up and build the overlay graphics. */
3099   sprite_vector_reserve(&t->sprites.city.worked_tile_overlay,
3100 			sprite_vector_size(&t->sprites.colors.overlays));
3101   sprite_vector_reserve(&t->sprites.city.unworked_tile_overlay,
3102 			sprite_vector_size(&t->sprites.colors.overlays));
3103   for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
3104     struct sprite *color, *color_mask;
3105     struct sprite *worked, *unworked;
3106 
3107     color = *sprite_vector_get(&t->sprites.colors.overlays, i);
3108     color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0,
3109                              1.0f, FALSE);
3110     worked = crop_sprite(color_mask, 0, 0, W, H,
3111 			 t->sprites.mask.worked_tile, 0, 0, 1.0f, FALSE);
3112     unworked = crop_sprite(color_mask, 0, 0, W, H,
3113 			   t->sprites.mask.unworked_tile, 0, 0, 1.0f, FALSE);
3114     free_sprite(color_mask);
3115     t->sprites.city.worked_tile_overlay.p[i] =  worked;
3116     t->sprites.city.unworked_tile_overlay.p[i] = unworked;
3117   }
3118 
3119 
3120   {
3121     SET_SPRITE(grid.unavailable, "grid.unavailable");
3122     SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
3123 
3124     for (i = 0; i < EDGE_COUNT; i++) {
3125       int be;
3126 
3127       if (i == EDGE_UD && t->hex_width == 0) {
3128 	continue;
3129       } else if (i == EDGE_LR && t->hex_height == 0) {
3130 	continue;
3131       }
3132 
3133       fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
3134       SET_SPRITE(grid.main[i], buffer);
3135 
3136       fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
3137       SET_SPRITE(grid.city[i], buffer);
3138 
3139       fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
3140       SET_SPRITE(grid.worked[i], buffer);
3141 
3142       fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
3143       SET_SPRITE(grid.selected[i], buffer);
3144 
3145       fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
3146       SET_SPRITE(grid.coastline[i], buffer);
3147 
3148       for (be = 0; be < 2; be++) {
3149         fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
3150                     edge_name[i][be]);
3151         SET_SPRITE(grid.borders[i][be], buffer);
3152       }
3153     }
3154   }
3155 
3156   switch (t->darkness_style) {
3157   case DARKNESS_NONE:
3158     /* Nothing. */
3159     break;
3160   case DARKNESS_ISORECT:
3161     {
3162       /* Isometric: take a single tx.darkness tile and split it into 4. */
3163       struct sprite *darkness = load_sprite(t, "tx.darkness", TRUE, FALSE);
3164       const int ntw = t->normal_tile_width, nth = t->normal_tile_height;
3165       int offsets[4][2] = {{ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
3166 
3167       if (!darkness) {
3168         tileset_error(LOG_FATAL, _("Sprite tx.darkness missing."));
3169       }
3170       for (i = 0; i < 4; i++) {
3171         t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
3172                                                 offsets[i][1], ntw / 2,
3173                                                 nth / 2, NULL, 0, 0, 1.0f,
3174                                                 FALSE);
3175       }
3176     }
3177     break;
3178   case DARKNESS_CARD_SINGLE:
3179     for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3180       enum direction8 dir = t->cardinal_tileset_dirs[i];
3181 
3182       fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3183 		  dir_get_tileset_name(dir));
3184       SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3185     }
3186     break;
3187   case DARKNESS_CARD_FULL:
3188     for(i = 1; i < t->num_index_cardinal; i++) {
3189       fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3190 		  cardinal_index_str(t, i));
3191       SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3192     }
3193     break;
3194   case DARKNESS_CORNER:
3195     t->sprites.tx.fullfog = fc_realloc(t->sprites.tx.fullfog,
3196 				       81 * sizeof(*t->sprites.tx.fullfog));
3197     for (i = 0; i < 81; i++) {
3198       /* Unknown, fog, known. */
3199       char ids[] = {'u', 'f', 'k'};
3200       char buf[512] = "t.fog";
3201       int values[4], vi, k = i;
3202 
3203       for (vi = 0; vi < 4; vi++) {
3204 	values[vi] = k % 3;
3205 	k /= 3;
3206 
3207 	cat_snprintf(buf, sizeof(buf), "_%c", ids[values[vi]]);
3208       }
3209       fc_assert(k == 0);
3210 
3211       t->sprites.tx.fullfog[i] = load_sprite(t, buf, TRUE, FALSE);
3212     }
3213     break;
3214   };
3215 
3216   /* no other place to initialize these variables */
3217   sprite_vector_init(&t->sprites.nation_flag);
3218   sprite_vector_init(&t->sprites.nation_shield);
3219 }
3220 
3221 /**************************************************************************
3222   Load sprites of one river type.
3223 **************************************************************************/
load_river_sprites(struct tileset * t,struct river_sprites * store,const char * tag_pfx)3224 static bool load_river_sprites(struct tileset *t,
3225                                struct river_sprites *store, const char *tag_pfx)
3226 {
3227   int i;
3228   char buffer[512];
3229 
3230   for (i = 0; i < t->num_index_cardinal; i++) {
3231     fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
3232                 tag_pfx, cardinal_index_str(t, i));
3233     store->spec[i] = load_sprite(t, buffer, TRUE, TRUE);
3234     if (store->spec[i] == NULL) {
3235       return FALSE;
3236     }
3237   }
3238 
3239   for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3240     fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%s",
3241                 tag_pfx, dir_get_tileset_name(t->cardinal_tileset_dirs[i]));
3242     store->outlet[i] = load_sprite(t, buffer, TRUE, TRUE);
3243     if (store->outlet[i] == NULL) {
3244       if (t->cardinal_tileset_dirs[i] == DIR8_NORTHWEST
3245           || t->cardinal_tileset_dirs[i] == DIR8_NORTHEAST
3246           || t->cardinal_tileset_dirs[i] == DIR8_SOUTHEAST
3247           || t->cardinal_tileset_dirs[i] == DIR8_SOUTHWEST) {
3248         log_debug("Missing \"%s\", support for this is deprecated.", buffer);
3249       } else {
3250         return FALSE;
3251       }
3252     }
3253   }
3254 
3255   return TRUE;
3256 }
3257 
3258 /**************************************************************************
3259   Frees any internal buffers which are created by load_sprite. Should
3260   be called after the last (for a given period of time) load_sprite
3261   call.  This saves a fair amount of memory, but it will take extra time
3262   the next time we start loading sprites again.
3263 **************************************************************************/
finish_loading_sprites(struct tileset * t)3264 void finish_loading_sprites(struct tileset *t)
3265 {
3266   specfile_list_iterate(t->specfiles, sf) {
3267     if (sf->big_sprite) {
3268       free_sprite(sf->big_sprite);
3269       sf->big_sprite = NULL;
3270     }
3271   } specfile_list_iterate_end;
3272 }
3273 
3274 /**********************************************************************
3275   Load the tiles; requires tilespec_read_toplevel() called previously.
3276   Leads to tile_sprites being allocated and filled with pointers
3277   to sprites.   Also sets up and populates sprite_hash, and calls func
3278   to initialize 'sprites' structure.
3279 ***********************************************************************/
tileset_load_tiles(struct tileset * t)3280 void tileset_load_tiles(struct tileset *t)
3281 {
3282   tileset_lookup_sprite_tags(t);
3283   finish_loading_sprites(t);
3284 }
3285 
3286 /**********************************************************************
3287   Lookup sprite to match tag, or else to match alt if don't find,
3288   or else return NULL, and emit log message.
3289 ***********************************************************************/
tiles_lookup_sprite_tag_alt(struct tileset * t,enum log_level level,const char * tag,const char * alt,const char * what,const char * name,bool scale)3290 struct sprite *tiles_lookup_sprite_tag_alt(struct tileset *t,
3291                                            enum log_level level,
3292                                            const char *tag, const char *alt,
3293                                            const char *what,
3294                                            const char *name,
3295                                            bool scale)
3296 {
3297   struct sprite *sp;
3298 
3299   /* (should get sprite_hash before connection) */
3300   fc_assert_ret_val_msg(NULL != t->sprite_hash, NULL,
3301                         "attempt to lookup for %s \"%s\" before "
3302                         "sprite_hash setup", what, name);
3303 
3304   sp = load_sprite(t, tag, scale, TRUE);
3305   if (sp) return sp;
3306 
3307   sp = load_sprite(t, alt, scale, TRUE);
3308   if (sp) {
3309     log_verbose("Using alternate graphic \"%s\" "
3310                 "(instead of \"%s\") for %s \"%s\".",
3311                 alt, tag, what, name);
3312     return sp;
3313   }
3314 
3315   tileset_error(level, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3316                   tag, alt, what, name);
3317 
3318   return NULL;
3319 }
3320 
3321 /**********************************************************************
3322   Helper function to load sprite for one unit orientation
3323 ***********************************************************************/
tileset_setup_unit_direction(struct tileset * t,int uidx,const char * base_str,enum direction8 dir,const char * dirsuffix)3324 static bool tileset_setup_unit_direction(struct tileset *t,
3325                                          int uidx,
3326                                          const char *base_str,
3327                                          enum direction8 dir,
3328                                          const char *dirsuffix)
3329 {
3330   char buf[2048];
3331 
3332   fc_snprintf(buf, sizeof(buf), "%s_%s", base_str, dirsuffix);
3333 
3334   /* We don't use _alt graphics here, as that could lead to loading
3335    * real icon gfx, but alternative orientation gfx. Tileset author
3336    * probably meant icon gfx to be used as fallback for all orientations */
3337   t->sprites.units.facing[uidx][dir] = load_sprite(t, buf, TRUE, TRUE);
3338 
3339   if (t->sprites.units.facing[uidx][dir] != NULL) {
3340     return TRUE;
3341   }
3342 
3343   return FALSE;
3344 }
3345 
3346 /**********************************************************************
3347   Try to setup all unit type sprites from single tag
3348 ***********************************************************************/
tileset_setup_unit_type_from_tag(struct tileset * t,int uidx,const char * tag)3349 static bool tileset_setup_unit_type_from_tag(struct tileset *t,
3350                                              int uidx, const char *tag)
3351 {
3352   bool facing_sprites = TRUE;
3353 
3354   t->sprites.units.icon[uidx] = load_sprite(t, tag, TRUE, TRUE);
3355 
3356 #define LOAD_FACING_SPRITE(dir, dname)                           \
3357   if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
3358     facing_sprites = FALSE;                                      \
3359   }
3360 
3361   LOAD_FACING_SPRITE(DIR8_NORTHWEST, "nw");
3362   LOAD_FACING_SPRITE(DIR8_NORTH, "n");
3363   LOAD_FACING_SPRITE(DIR8_NORTHEAST, "ne");
3364   LOAD_FACING_SPRITE(DIR8_WEST, "w");
3365   LOAD_FACING_SPRITE(DIR8_EAST, "e");
3366   LOAD_FACING_SPRITE(DIR8_SOUTHWEST, "sw");
3367   LOAD_FACING_SPRITE(DIR8_SOUTH, "s");
3368   LOAD_FACING_SPRITE(DIR8_SOUTHEAST, "se");
3369 
3370   if (!facing_sprites && t->sprites.units.icon[uidx] == NULL) {
3371     /* Neither icon gfx or orientation sprites */
3372     return FALSE;
3373   }
3374 
3375   /* Fix a random orientation for displaying unit type in help etc.
3376    * We don't necessarily know the map topology yet, so choose a seed
3377    * that can be used to pick a valid direction later (24 is lcm(6,8)).
3378    * See get_unittype_sprite(). */
3379   t->sprites.units.default_dir_seed[uidx] = fc_rand(24);
3380 
3381   return TRUE;
3382 
3383 #undef LOAD_FACING_SPRITE
3384 }
3385 
3386 /**********************************************************************
3387   Set unit_type sprite value; should only happen after
3388   tilespec_load_tiles().
3389 ***********************************************************************/
tileset_setup_unit_type(struct tileset * t,struct unit_type * ut)3390 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
3391 {
3392   int uidx = utype_index(ut);
3393 
3394   if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
3395       && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
3396     tileset_error(LOG_FATAL, _("Missing %s unit sprite for tags \"%s\" and alternative \"%s\"."),
3397                   utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
3398   }
3399 }
3400 
3401 /**********************************************************************
3402   Set improvement_type sprite value; should only happen after
3403   tilespec_load_tiles().
3404 ***********************************************************************/
tileset_setup_impr_type(struct tileset * t,struct impr_type * pimprove)3405 void tileset_setup_impr_type(struct tileset *t,
3406 			     struct impr_type *pimprove)
3407 {
3408   t->sprites.building[improvement_index(pimprove)] =
3409     tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, pimprove->graphic_str,
3410 				pimprove->graphic_alt, "improvement",
3411 				improvement_rule_name(pimprove), FALSE);
3412 
3413   /* should maybe do something if NULL, eg generic default? */
3414 }
3415 
3416 /**********************************************************************
3417   Set tech_type sprite value; should only happen after
3418   tilespec_load_tiles().
3419 ***********************************************************************/
tileset_setup_tech_type(struct tileset * t,struct advance * padvance)3420 void tileset_setup_tech_type(struct tileset *t,
3421 			     struct advance *padvance)
3422 {
3423   if (valid_advance(padvance)) {
3424     t->sprites.tech[advance_index(padvance)] =
3425       tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, padvance->graphic_str,
3426 				  padvance->graphic_alt, "technology",
3427 				  advance_rule_name(padvance), FALSE);
3428 
3429     /* should maybe do something if NULL, eg generic default? */
3430   } else {
3431     t->sprites.tech[advance_index(padvance)] = NULL;
3432   }
3433 }
3434 
3435 /****************************************************************************
3436   Set resource sprite values; should only happen after
3437   tilespec_load_tiles().
3438 ****************************************************************************/
tileset_setup_resource(struct tileset * t,const struct resource * presource)3439 void tileset_setup_resource(struct tileset *t,
3440                             const struct resource *presource)
3441 {
3442   fc_assert_ret(NULL != presource);
3443   t->sprites.resource[resource_index(presource)] =
3444     tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, presource->graphic_str,
3445                                 presource->graphic_alt, "resource",
3446                                 resource_rule_name(presource), TRUE);
3447 }
3448 
3449 /****************************************************************************
3450   Set extra sprite values; should only happen after
3451   tilespec_load_tiles().
3452 ****************************************************************************/
tileset_setup_extra(struct tileset * t,struct extra_type * pextra)3453 void tileset_setup_extra(struct tileset *t,
3454                          struct extra_type *pextra)
3455 {
3456   const int id = extra_index(pextra);
3457   enum extrastyle_id extrastyle;
3458 
3459   if (!fc_strcasecmp(pextra->graphic_str, "none")) {
3460     /* Extra without graphics */
3461     t->sprites.extras[id].extrastyle = extrastyle_id_invalid();
3462   } else {
3463 
3464     if (!estyle_hash_lookup(t->estyle_hash, pextra->graphic_str,
3465                             &extrastyle)
3466         && !estyle_hash_lookup(t->estyle_hash, pextra->graphic_alt,
3467                                &extrastyle)) {
3468       tileset_error(LOG_FATAL, _("No extrastyle for \"%s\" or \"%s\"."),
3469                     pextra->graphic_str,
3470                     pextra->graphic_alt);
3471     }
3472 
3473     t->sprites.extras[id].extrastyle = extrastyle;
3474 
3475     extra_type_list_append(t->style_lists[extrastyle], pextra);
3476 
3477     if (extra_has_flag(pextra, EF_SHOW_FLAG)) {
3478       extra_type_list_append(t->flagged_bases_list, pextra);
3479     }
3480 
3481     switch (extrastyle) {
3482     case ESTYLE_3LAYER:
3483       tileset_setup_base(t, pextra);
3484       break;
3485 
3486     case ESTYLE_ROAD_ALL_SEPARATE:
3487     case ESTYLE_ROAD_PARITY_COMBINED:
3488     case ESTYLE_ROAD_ALL_COMBINED:
3489     case ESTYLE_RIVER:
3490       tileset_setup_road(t, pextra);
3491       break;
3492 
3493     case ESTYLE_SINGLE1:
3494     case ESTYLE_SINGLE2:
3495       SET_SPRITE_ALT(extras[id].u.single, pextra->graphic_str, pextra->graphic_alt);
3496       break;
3497 
3498     case ESTYLE_CARDINALS:
3499       {
3500         int i;
3501         char buffer[512];
3502 
3503         /* We use direction-specific irrigation and farmland graphics, if they
3504          * are available.  If not, we just fall back to the basic irrigation
3505          * graphics. */
3506         for (i = 0; i < t->num_index_cardinal; i++) {
3507           fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3508                       pextra->graphic_str, cardinal_index_str(t, i));
3509           t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3510                                                              TRUE, TRUE);
3511           if (!t->sprites.extras[id].u.cardinals[i]) {
3512             t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3513                                                   pextra->graphic_str, TRUE,
3514                                                   TRUE);
3515           }
3516           if (!t->sprites.extras[id].u.cardinals[i]) {
3517             fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3518                         pextra->graphic_alt, cardinal_index_str(t, i));
3519             t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3520                                                                TRUE, TRUE);
3521           }
3522           if (!t->sprites.extras[id].u.cardinals[i]) {
3523             t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3524                                                   pextra->graphic_alt, TRUE,
3525                                                   TRUE);
3526           }
3527           if (!t->sprites.extras[id].u.cardinals[i]) {
3528             tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are "
3529                                        "both missing."),
3530                           pextra->graphic_str, pextra->graphic_alt);
3531           }
3532         }
3533       }
3534       break;
3535     case ESTYLE_COUNT:
3536       break;
3537     }
3538   }
3539 
3540   if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
3541     t->sprites.extras[id].activity = NULL;
3542   } else {
3543     t->sprites.extras[id].activity = load_sprite(t, pextra->activity_gfx,
3544                                                  TRUE, TRUE);
3545     if (t->sprites.extras[id].activity == NULL) {
3546       t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt,
3547                                                    TRUE, TRUE);
3548     }
3549     if (t->sprites.extras[id].activity == NULL) {
3550       t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt2,
3551                                                    TRUE, TRUE);
3552     }
3553     if (t->sprites.extras[id].activity == NULL) {
3554       tileset_error(LOG_FATAL, _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
3555                     extra_rule_name(pextra), pextra->activity_gfx,
3556                     pextra->act_gfx_alt, pextra->act_gfx_alt2);
3557     }
3558   }
3559 
3560   if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
3561     t->sprites.extras[id].rmact = NULL;
3562   } else {
3563     t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx, TRUE,
3564                                               TRUE);
3565     if (t->sprites.extras[id].rmact == NULL) {
3566       t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx_alt,
3567                                                 TRUE, TRUE);
3568       if (t->sprites.extras[id].rmact == NULL) {
3569         tileset_error(LOG_FATAL, _("Missing %s removal activity sprite for tags \"%s\" and alternative \"%s\"."),
3570                       extra_rule_name(pextra), pextra->rmact_gfx, pextra->rmact_gfx_alt);
3571       }
3572     }
3573   }
3574 }
3575 
3576 /****************************************************************************
3577   Set road sprite values; should only happen after
3578   tilespec_load_tiles().
3579 ****************************************************************************/
tileset_setup_road(struct tileset * t,struct extra_type * pextra)3580 static void tileset_setup_road(struct tileset *t,
3581                                struct extra_type *pextra)
3582 {
3583   char full_tag_name[MAX_LEN_NAME + strlen("_isolated")];
3584   char full_alt_name[MAX_LEN_NAME + strlen("_isolated")];
3585   const int id = extra_index(pextra);
3586   int i;
3587   enum extrastyle_id extrastyle = t->sprites.extras[id].extrastyle;
3588 
3589   /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3590      ESTYLE_ROAD_PARITY_COMBINED. */
3591   if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3592       || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3593     fc_snprintf(full_tag_name, sizeof(full_tag_name),
3594                 "%s_isolated", pextra->graphic_str);
3595     fc_snprintf(full_alt_name, sizeof(full_alt_name),
3596                 "%s_isolated", pextra->graphic_alt);
3597 
3598     SET_SPRITE_ALT(extras[id].u.road.isolated, full_tag_name, full_alt_name);
3599   }
3600 
3601   if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
3602     /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each road type:
3603      * one going off in each direction. */
3604     for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3605       enum direction8 dir = t->valid_tileset_dirs[i];
3606       const char *dir_name = dir_get_tileset_name(dir);
3607 
3608       fc_snprintf(full_tag_name, sizeof(full_tag_name),
3609                   "%s_%s", pextra->graphic_str, dir_name);
3610       fc_snprintf(full_alt_name, sizeof(full_alt_name),
3611                   "%s_%s", pextra->graphic_alt, dir_name);
3612 
3613       SET_SPRITE_ALT(extras[id].u.road.ru.dir[i], full_tag_name, full_alt_name);
3614     }
3615   } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3616     int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
3617 
3618     /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road type:
3619      * 16 each for cardinal and diagonal directions.  Each set
3620      * of 16 provides a NSEW-indexed sprite to provide connectors for
3621      * all rails in the cardinal/diagonal directions.  The 0 entry is
3622      * unused (the "isolated" sprite is used instead). */
3623 
3624     for (i = 1; i < num_index; i++) {
3625       char c[64] = "", d[64] = "";
3626 
3627       for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
3628 	int value = (i >> j) & 1;
3629 
3630 	cat_snprintf(c, sizeof(c), "%s%d",
3631 		     dir_get_tileset_name(t->valid_tileset_dirs[2 * j]),
3632 		     value);
3633 	cat_snprintf(d, sizeof(d), "%s%d",
3634 		     dir_get_tileset_name(t->valid_tileset_dirs[2 * j + 1]),
3635 		     value);
3636       }
3637 
3638       fc_snprintf(full_tag_name, sizeof(full_tag_name),
3639                   "%s_c_%s", pextra->graphic_str, c);
3640       fc_snprintf(full_alt_name, sizeof(full_alt_name),
3641                   "%s_c_%s", pextra->graphic_alt, c);
3642 
3643       SET_SPRITE_ALT(extras[id].u.road.ru.combo.even[i], full_tag_name, full_alt_name);
3644 
3645       fc_snprintf(full_tag_name, sizeof(full_tag_name),
3646                   "%s_d_%s", pextra->graphic_str, d);
3647       fc_snprintf(full_alt_name, sizeof(full_alt_name),
3648                   "%s_d_%s", pextra->graphic_alt, d);
3649 
3650       SET_SPRITE_ALT(extras[id].u.road.ru.combo.odd[i], full_tag_name, full_alt_name);
3651     }
3652   } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
3653     /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
3654      * Just go around clockwise, with all combinations. */
3655     for (i = 0; i < t->num_index_valid; i++) {
3656       char *idx_str = valid_index_str(t, i);
3657 
3658       fc_snprintf(full_tag_name, sizeof(full_tag_name),
3659                   "%s_%s", pextra->graphic_str, idx_str);
3660       fc_snprintf(full_alt_name, sizeof(full_alt_name),
3661                   "%s_%s", pextra->graphic_alt, idx_str);
3662 
3663       SET_SPRITE_ALT(extras[id].u.road.ru.total[i], full_tag_name, full_alt_name);
3664     }
3665   } else if (extrastyle == ESTYLE_RIVER) {
3666     if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3667                             pextra->graphic_str)) {
3668       if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3669                               pextra->graphic_alt)) {
3670         tileset_error(LOG_FATAL, _("Cannot load river \"%s\" or \"%s\""),
3671                       pextra->graphic_str, pextra->graphic_alt);
3672       }
3673     }
3674   } else {
3675     fc_assert(FALSE);
3676   }
3677 
3678   /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3679    * ESTYLE_ROAD_PARITY_COMBINED. */
3680   if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3681       || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3682     for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3683       enum direction8 dir = t->valid_tileset_dirs[i];
3684 
3685       if (!is_cardinal_tileset_dir(t, dir)) {
3686         const char *dtn = dir_get_tileset_name(dir);
3687 
3688         fc_snprintf(full_tag_name, sizeof(full_tag_name),
3689                     "%s_c_%s", pextra->graphic_str, dtn);
3690         fc_snprintf(full_alt_name, sizeof(full_alt_name),
3691                     "%s_c_%s", pextra->graphic_alt, dtn);
3692 
3693         SET_SPRITE_ALT_OPT(extras[id].u.road.corner[dir], full_tag_name, full_alt_name);
3694       }
3695     }
3696   }
3697 }
3698 
3699 /****************************************************************************
3700   Set base sprite values; should only happen after
3701   tilespec_load_tiles().
3702 ****************************************************************************/
tileset_setup_base(struct tileset * t,const struct extra_type * pextra)3703 static void tileset_setup_base(struct tileset *t,
3704                                const struct extra_type *pextra)
3705 {
3706   char full_tag_name[MAX_LEN_NAME + strlen("_fg")];
3707   const int id = extra_index(pextra);
3708 
3709   fc_assert_ret(id >= 0 && id < extra_count());
3710 
3711   sz_strlcpy(full_tag_name, pextra->graphic_str);
3712   strcat(full_tag_name, "_bg");
3713   t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3714                                                        TRUE, TRUE);
3715 
3716   sz_strlcpy(full_tag_name, pextra->graphic_str);
3717   strcat(full_tag_name, "_mg");
3718   t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3719                                                          TRUE, TRUE);
3720 
3721   sz_strlcpy(full_tag_name, pextra->graphic_str);
3722   strcat(full_tag_name, "_fg");
3723   t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3724                                                        TRUE, TRUE);
3725 
3726   if (t->sprites.extras[id].u.bmf.background == NULL
3727       && t->sprites.extras[id].u.bmf.middleground == NULL
3728       && t->sprites.extras[id].u.bmf.foreground == NULL) {
3729     /* No primary graphics at all. Try alternative */
3730     log_verbose("Using alternate graphic \"%s\" "
3731                 "(instead of \"%s\") for extra \"%s\".",
3732                 pextra->graphic_alt, pextra->graphic_str,
3733                 extra_rule_name(pextra));
3734 
3735     sz_strlcpy(full_tag_name, pextra->graphic_alt);
3736     strcat(full_tag_name, "_bg");
3737     t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3738                                                          TRUE, TRUE);
3739 
3740     sz_strlcpy(full_tag_name, pextra->graphic_alt);
3741     strcat(full_tag_name, "_mg");
3742     t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3743                                                            TRUE, TRUE);
3744 
3745     sz_strlcpy(full_tag_name, pextra->graphic_alt);
3746     strcat(full_tag_name, "_fg");
3747     t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3748                                                          TRUE, TRUE);
3749 
3750     if (t->sprites.extras[id].u.bmf.background == NULL
3751         && t->sprites.extras[id].u.bmf.middleground == NULL
3752         && t->sprites.extras[id].u.bmf.foreground == NULL) {
3753       /* Cannot find alternative graphics either */
3754       tileset_error(LOG_FATAL, _("No graphics for extra \"%s\" at all!"),
3755                     extra_rule_name(pextra));
3756     }
3757   }
3758 }
3759 
3760 /**********************************************************************
3761   Set tile_type sprite values; should only happen after
3762   tilespec_load_tiles().
3763 ***********************************************************************/
tileset_setup_tile_type(struct tileset * t,const struct terrain * pterrain)3764 void tileset_setup_tile_type(struct tileset *t,
3765 			     const struct terrain *pterrain)
3766 {
3767   struct drawing_data *draw;
3768   struct sprite *sprite;
3769   char buffer[MAX_LEN_NAME + 20];
3770   int i, l;
3771 
3772   if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
3773       && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
3774     tileset_error(LOG_FATAL, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3775                   terrain_rule_name(pterrain), pterrain->graphic_str,
3776                   pterrain->graphic_alt);
3777   }
3778 
3779   if (draw->init) {
3780     t->sprites.drawing[terrain_index(pterrain)] = draw;
3781     return;
3782   }
3783 
3784   /* Set up each layer of the drawing. */
3785   for (l = 0; l < draw->num_layers; l++) {
3786     struct drawing_layer *dlp = &draw->layer[l];
3787     struct tileset_layer *tslp = &t->layers[l];
3788     sprite_vector_init(&dlp->base);
3789     sprite_vector_init(&dlp->allocated);
3790 
3791     switch (dlp->sprite_type) {
3792     case CELL_WHOLE:
3793       switch (dlp->match_style) {
3794       case MATCH_NONE:
3795 	/* Load whole sprites for this tile. */
3796 	for (i = 0; ; i++) {
3797           fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
3798                       l, draw->name, i + 1);
3799 	  sprite = load_sprite(t, buffer, TRUE, FALSE);
3800 	  if (!sprite) {
3801 	    break;
3802 	  }
3803 	  sprite_vector_reserve(&dlp->base, i + 1);
3804 	  dlp->base.p[i] = sprite;
3805 	}
3806 	/* check for base sprite, allowing missing sprites above base */
3807 	if (0 == i  &&  0 == l) {
3808           /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
3809           tileset_error(LOG_FATAL, _("Missing base sprite for tag \"%s\"."), buffer);
3810 	}
3811 	break;
3812       case MATCH_SAME:
3813 	/* Load 16 cardinally-matched sprites. */
3814 	for (i = 0; i < t->num_index_cardinal; i++) {
3815           fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
3816                       l, draw->name, cardinal_index_str(t, i));
3817 	  dlp->match[i] =
3818 	    tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3819 					"matched terrain",
3820 					terrain_rule_name(pterrain), TRUE);
3821 	}
3822 	break;
3823       case MATCH_PAIR:
3824       case MATCH_FULL:
3825         fc_assert(FALSE); /* not yet defined */
3826         break;
3827       };
3828       break;
3829     case CELL_CORNER:
3830       {
3831 	const int count = dlp->match_indices;
3832 	int number = NUM_CORNER_DIRS;
3833 
3834 	switch (dlp->match_style) {
3835 	case MATCH_NONE:
3836 	  /* do nothing */
3837 	  break;
3838 	case MATCH_PAIR:
3839 	case MATCH_SAME:
3840 	  /* N directions (NSEW) * 3 dimensions of matching */
3841           fc_assert(count == 2);
3842 	  number = NUM_CORNER_DIRS * 2 * 2 * 2;
3843 	  break;
3844 	case MATCH_FULL:
3845 	default:
3846 	  /* N directions (NSEW) * 3 dimensions of matching */
3847 	  /* could use exp() or expi() here? */
3848 	  number = NUM_CORNER_DIRS * count * count * count;
3849 	  break;
3850 	};
3851 
3852 	dlp->cells
3853 	  = fc_calloc(number, sizeof(*dlp->cells));
3854 
3855 	for (i = 0; i < number; i++) {
3856 	  enum direction4 dir = i % NUM_CORNER_DIRS;
3857 	  int value = i / NUM_CORNER_DIRS;
3858 
3859 	  switch (dlp->match_style) {
3860 	  case MATCH_NONE:
3861             fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
3862                         l, draw->name, direction4letters[dir]);
3863 	    dlp->cells[i] =
3864 	      tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3865 					  "cell terrain",
3866 					  terrain_rule_name(pterrain), TRUE);
3867 	    break;
3868 	  case MATCH_SAME:
3869             fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
3870                         l, draw->name, direction4letters[dir],
3871                         (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
3872 	    dlp->cells[i] =
3873 	      tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3874 					  "same cell terrain",
3875 					  terrain_rule_name(pterrain), TRUE);
3876 	    break;
3877 	  case MATCH_PAIR:
3878             fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
3879                         l, draw->name, direction4letters[dir],
3880                         tslp->match_types[dlp->match_index[(value) & 1]][0],
3881                         tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
3882                         tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
3883 	    dlp->cells[i] =
3884 	      tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3885 					  "cell pair terrain",
3886 					  terrain_rule_name(pterrain), TRUE);
3887 	    break;
3888 	  case MATCH_FULL:
3889 	    {
3890 	      int this = dlp->match_index[0];
3891 	      int n, s, e, w;
3892 	      int v1, v2, v3;
3893 
3894 	      v1 = dlp->match_index[value % count];
3895 	      value /= count;
3896 	      v2 = dlp->match_index[value % count];
3897 	      value /= count;
3898 	      v3 = dlp->match_index[value % count];
3899 
3900               fc_assert(v1 < count && v2 < count && v3 < count);
3901 
3902 	      /* Assume merged cells.  This should be a separate option. */
3903 	      switch (dir) {
3904 	      case DIR4_NORTH:
3905 		s = this;
3906 		w = v1;
3907 		n = v2;
3908 		e = v3;
3909 		break;
3910 	      case DIR4_EAST:
3911 		w = this;
3912 		n = v1;
3913 		e = v2;
3914 		s = v3;
3915 		break;
3916 	      case DIR4_SOUTH:
3917 		n = this;
3918 		e = v1;
3919 		s = v2;
3920 		w = v3;
3921 		break;
3922 	      case DIR4_WEST:
3923 	      default:		/* avoid warnings */
3924 		e = this;
3925 		s = v1;
3926 		w = v2;
3927 		n = v3;
3928 		break;
3929 	      };
3930 
3931 	      /* Use first character of match_types,
3932 	       * already checked for uniqueness. */
3933               fc_snprintf(buffer, sizeof(buffer),
3934                           "t.l%d.cellgroup_%c_%c_%c_%c", l,
3935                           tslp->match_types[n][0], tslp->match_types[e][0],
3936                           tslp->match_types[s][0], tslp->match_types[w][0]);
3937 	      sprite = load_sprite(t, buffer, TRUE, FALSE);
3938 
3939 	      if (sprite) {
3940 		/* Crop the sprite to separate this cell. */
3941                 int vec_size = sprite_vector_size(&dlp->allocated);
3942 
3943 		const int W = t->normal_tile_width;
3944 		const int H = t->normal_tile_height;
3945 		int x[4] = {W / 4, W / 4, 0, W / 2};
3946 		int y[4] = {H / 2, 0, H / 4, H / 4};
3947 		int xo[4] = {0, 0, -W / 2, W / 2};
3948 		int yo[4] = {H / 2, -H / 2, 0, 0};
3949 
3950         sprite = crop_sprite(sprite, x[dir], y[dir], W / 2, H / 2,
3951                              t->sprites.mask.tile, xo[dir], yo[dir], 1.0f,
3952                              FALSE);
3953                 /* We allocated new sprite with crop_sprite. Store its
3954                  * address so we can free it. */
3955                 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
3956                 dlp->allocated.p[vec_size] = sprite;
3957 	      } else {
3958                 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer);
3959 	      }
3960 
3961 	      dlp->cells[i] = sprite;
3962 	    }
3963 	    break;
3964 	  };
3965 	}
3966       }
3967       break;
3968     };
3969   }
3970 
3971   /* try an optional special name */
3972   fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
3973   draw->blender =
3974     tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, buffer, "",
3975 				"blend terrain",
3976 				terrain_rule_name(pterrain), TRUE);
3977 
3978   if (draw->blending > 0) {
3979     const int bl = draw->blending - 1;
3980 
3981     if (NULL == draw->blender) {
3982       int li = 0;
3983 
3984       /* try an already loaded base */
3985       while (NULL == draw->blender
3986         &&  li < draw->blending
3987         &&  0 < draw->layer[li].base.size) {
3988         draw->blender = draw->layer[li++].base.p[0];
3989       }
3990     }
3991 
3992     if (NULL == draw->blender) {
3993       /* try an unloaded base name */
3994       fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", bl, draw->name);
3995       draw->blender =
3996 	tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3997 				    "base (blend) terrain",
3998 				    terrain_rule_name(pterrain), TRUE);
3999     }
4000   }
4001 
4002   if (NULL != draw->blender) {
4003     /* Set up blending sprites. This only works in iso-view! */
4004     const int W = t->normal_tile_width;
4005     const int H = t->normal_tile_height;
4006     const int offsets[4][2] = {
4007       {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4008     };
4009     enum direction4 dir = 0;
4010 
4011     for (; dir < 4; dir++) {
4012       draw->blend[dir] = crop_sprite(draw->blender, offsets[dir][0],
4013                                      offsets[dir][1], W / 2, H / 2,
4014                                      t->sprites.dither_tile, 0, 0, 1.0f,
4015                                      FALSE);
4016     }
4017   }
4018 
4019   draw->init = TRUE;
4020   t->sprites.drawing[terrain_index(pterrain)] = draw;
4021 }
4022 
4023 /**********************************************************************
4024   Set government sprite value; should only happen after
4025   tilespec_load_tiles().
4026 ***********************************************************************/
tileset_setup_government(struct tileset * t,struct government * gov)4027 void tileset_setup_government(struct tileset *t,
4028 			      struct government *gov)
4029 {
4030   t->sprites.government[government_index(gov)] =
4031     tiles_lookup_sprite_tag_alt(t, LOG_FATAL, gov->graphic_str,
4032 				gov->graphic_alt, "government",
4033 				government_rule_name(gov), FALSE);
4034 
4035   /* should probably do something if NULL, eg generic default? */
4036 }
4037 
4038 /**********************************************************************
4039   Set nation flag sprite value; should only happen after
4040   tilespec_load_tiles().
4041 ***********************************************************************/
tileset_setup_nation_flag(struct tileset * t,struct nation_type * nation)4042 void tileset_setup_nation_flag(struct tileset *t,
4043 			       struct nation_type *nation)
4044 {
4045   char *tags[] = {nation->flag_graphic_str,
4046 		  nation->flag_graphic_alt,
4047 		  "unknown", NULL};
4048   int i;
4049   struct sprite *flag = NULL, *shield = NULL;
4050   char buf[1024];
4051 
4052   for (i = 0; tags[i] && !flag; i++) {
4053     fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
4054     flag = load_sprite(t, buf, TRUE, TRUE);
4055   }
4056   for (i = 0; tags[i] && !shield; i++) {
4057     fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
4058     shield = load_sprite(t, buf, TRUE, TRUE);
4059   }
4060   if (!flag || !shield) {
4061     /* Should never get here because of the f.unknown fallback. */
4062     tileset_error(LOG_FATAL, _("Nation %s: no national flag."), nation_rule_name(nation));
4063   }
4064 
4065   sprite_vector_reserve(&t->sprites.nation_flag, nation_count());
4066   t->sprites.nation_flag.p[nation_index(nation)] = flag;
4067 
4068   sprite_vector_reserve(&t->sprites.nation_shield, nation_count());
4069   t->sprites.nation_shield.p[nation_index(nation)] = shield;
4070 }
4071 
4072 /**********************************************************************
4073   Return the flag graphic to be used by the city.
4074 ***********************************************************************/
get_city_flag_sprite(const struct tileset * t,const struct city * pcity)4075 struct sprite *get_city_flag_sprite(const struct tileset *t,
4076 				    const struct city *pcity)
4077 {
4078   return get_nation_flag_sprite(t, nation_of_city(pcity));
4079 }
4080 
4081 /**********************************************************************
4082   Return a sprite for the national flag for this unit.
4083 ***********************************************************************/
get_unit_nation_flag_sprite(const struct tileset * t,const struct unit * punit)4084 static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
4085 						  const struct unit *punit)
4086 {
4087   struct nation_type *pnation = nation_of_unit(punit);
4088 
4089   if (gui_options.draw_unit_shields) {
4090     return t->sprites.nation_shield.p[nation_index(pnation)];
4091   } else {
4092     return t->sprites.nation_flag.p[nation_index(pnation)];
4093   }
4094 }
4095 
4096 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
4097 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
4098 
4099 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset)			    \
4100   (fc_assert(s != NULL),						    \
4101    sprs->sprite = s,							    \
4102    sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO),		    \
4103    sprs->offset_x = x_offset,						    \
4104    sprs->offset_y = y_offset,						    \
4105    sprs++)
4106 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
4107 #define ADD_SPRITE_FULL(s)						    \
4108   ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4109 
4110 /**************************************************************************
4111   Assemble some data that is used in building the tile sprite arrays.
4112     (map_x, map_y) : the (normalized) map position
4113   The values we fill in:
4114     tterrain_near  : terrain types of all adjacent terrain
4115     tspecial_near  : specials of all adjacent terrain
4116 **************************************************************************/
build_tile_data(const struct tile * ptile,struct terrain * pterrain,struct terrain ** tterrain_near,bv_extras * textras_near)4117 static void build_tile_data(const struct tile *ptile,
4118 			    struct terrain *pterrain,
4119 			    struct terrain **tterrain_near,
4120 			    bv_extras *textras_near)
4121 {
4122   enum direction8 dir;
4123 
4124   /* Loop over all adjacent tiles.  We should have an iterator for this. */
4125   for (dir = 0; dir < 8; dir++) {
4126     struct tile *tile1 = mapstep(ptile, dir);
4127 
4128     if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
4129       struct terrain *terrain1 = tile_terrain(tile1);
4130 
4131       if (NULL != terrain1) {
4132         tterrain_near[dir] = terrain1;
4133         textras_near[dir] = *tile_extras(tile1);
4134         continue;
4135       }
4136       log_error("build_tile_data() tile (%d,%d) has no terrain!",
4137                 TILE_XY(tile1));
4138     }
4139     /* At the edges of the (known) map, pretend the same terrain continued
4140      * past the edge of the map. */
4141     tterrain_near[dir] = pterrain;
4142     BV_CLR_ALL(textras_near[dir]);
4143   }
4144 }
4145 
4146 /**********************************************************************
4147   Fill in the sprite array for the unit type.
4148 ***********************************************************************/
fill_unit_type_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct unit_type * putype,enum direction8 facing)4149 static int fill_unit_type_sprite_array(const struct tileset *t,
4150                                        struct drawn_sprite *sprs,
4151                                        const struct unit_type *putype,
4152                                        enum direction8 facing)
4153 {
4154   struct drawn_sprite *save_sprs = sprs;
4155   struct sprite *uspr = get_unittype_sprite(t, putype, facing, FALSE);
4156 
4157   ADD_SPRITE(uspr, TRUE,
4158              FULL_TILE_X_OFFSET + t->unit_offset_x,
4159              FULL_TILE_Y_OFFSET + t->unit_offset_y);
4160 
4161   return sprs - save_sprs;
4162 }
4163 
4164 /**********************************************************************
4165   Fill in the sprite array for the unit.
4166 ***********************************************************************/
fill_unit_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct unit * punit,bool stack,bool backdrop)4167 static int fill_unit_sprite_array(const struct tileset *t,
4168                                   struct drawn_sprite *sprs,
4169                                   const struct unit *punit,
4170                                   bool stack, bool backdrop)
4171 {
4172   struct drawn_sprite *save_sprs = sprs;
4173   int ihp;
4174   struct unit_type *ptype = unit_type_get(punit);
4175 
4176   if (backdrop) {
4177     if (!gui_options.solid_color_behind_units) {
4178       ADD_SPRITE(get_unit_nation_flag_sprite(t, punit), TRUE,
4179 		 FULL_TILE_X_OFFSET + t->unit_flag_offset_x,
4180 		 FULL_TILE_Y_OFFSET + t->unit_flag_offset_y);
4181     } else {
4182       /* Taken care of in the LAYER_BACKGROUND. */
4183     }
4184   }
4185 
4186   /* Add the sprite for the unit type. */
4187   sprs += fill_unit_type_sprite_array(t, sprs, ptype,
4188                                       punit->facing);
4189 
4190   if (t->sprites.unit.loaded && unit_transported(punit)) {
4191     ADD_SPRITE_FULL(t->sprites.unit.loaded);
4192   }
4193 
4194   if (punit->activity != ACTIVITY_IDLE) {
4195     struct sprite *s = NULL;
4196 
4197     switch (punit->activity) {
4198     case ACTIVITY_MINE:
4199       if (punit->activity_target == NULL) {
4200         s = t->sprites.unit.plant;
4201       } else {
4202         s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4203       }
4204       break;
4205     case ACTIVITY_IRRIGATE:
4206      if (punit->activity_target == NULL) {
4207         s = t->sprites.unit.irrigate;
4208       } else {
4209         s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4210       }
4211       break;
4212     case ACTIVITY_POLLUTION:
4213     case ACTIVITY_FALLOUT:
4214       s = t->sprites.extras[extra_index(punit->activity_target)].rmact;
4215       break;
4216     case ACTIVITY_PILLAGE:
4217       s = t->sprites.unit.pillage;
4218       break;
4219     case ACTIVITY_EXPLORE:
4220       s = t->sprites.unit.auto_explore;
4221       break;
4222     case ACTIVITY_FORTIFIED:
4223       s = t->sprites.unit.fortified;
4224       break;
4225     case ACTIVITY_FORTIFYING:
4226       s = t->sprites.unit.fortifying;
4227       break;
4228     case ACTIVITY_SENTRY:
4229       s = t->sprites.unit.sentry;
4230       break;
4231     case ACTIVITY_GOTO:
4232       s = t->sprites.unit.go_to;
4233       break;
4234     case ACTIVITY_TRANSFORM:
4235       s = t->sprites.unit.transform;
4236       break;
4237     case ACTIVITY_BASE:
4238     case ACTIVITY_GEN_ROAD:
4239       s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4240       break;
4241     case ACTIVITY_CONVERT:
4242       s = t->sprites.unit.convert;
4243       break;
4244     default:
4245       break;
4246     }
4247 
4248     if (s != NULL) {
4249       ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4250                  FULL_TILE_Y_OFFSET + t->activity_offset_y);
4251     }
4252   }
4253 
4254   if (punit->ai_controlled && punit->activity != ACTIVITY_EXPLORE) {
4255     if (is_military_unit(punit)) {
4256       ADD_SPRITE_FULL(t->sprites.unit.auto_attack);
4257     } else {
4258       ADD_SPRITE_FULL(t->sprites.unit.auto_settler);
4259     }
4260   }
4261 
4262   if (unit_has_orders(punit)) {
4263     if (punit->orders.repeat) {
4264       ADD_SPRITE_FULL(t->sprites.unit.patrol);
4265     } else if (punit->activity != ACTIVITY_IDLE) {
4266       ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
4267     } else {
4268       ADD_SPRITE(t->sprites.unit.go_to, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4269                  FULL_TILE_Y_OFFSET + t->activity_offset_y);
4270     }
4271   }
4272 
4273   if (punit->battlegroup != BATTLEGROUP_NONE) {
4274     ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
4275   }
4276 
4277   if (t->sprites.unit.lowfuel
4278       && utype_fuel(ptype)
4279       && punit->fuel == 1
4280       && punit->moves_left <= 2 * SINGLE_MOVE) {
4281     /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4282     ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
4283   }
4284   if (t->sprites.unit.tired
4285       && punit->moves_left < SINGLE_MOVE
4286       && ptype->move_rate > 0) {
4287     /* Show a "tired" graphic if the unit has fewer than one move
4288      * remaining, except for units for which it's full movement. */
4289     ADD_SPRITE_FULL(t->sprites.unit.tired);
4290   }
4291 
4292   if (stack || punit->client.occupied) {
4293     ADD_SPRITE_FULL(t->sprites.unit.stack);
4294   }
4295 
4296   if (t->sprites.unit.vet_lev[punit->veteran]) {
4297     ADD_SPRITE_FULL(t->sprites.unit.vet_lev[punit->veteran]);
4298   }
4299 
4300   ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
4301   ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
4302   ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
4303 
4304   return sprs - save_sprs;
4305 }
4306 
4307 /**************************************************************************
4308   Add any corner road sprites to the sprite array.
4309 **************************************************************************/
fill_road_corner_sprites(const struct tileset * t,const struct extra_type * pextra,struct drawn_sprite * sprs,bool road,bool * road_near,bool hider,bool * hider_near)4310 static int fill_road_corner_sprites(const struct tileset *t,
4311                                     const struct extra_type *pextra,
4312 				    struct drawn_sprite *sprs,
4313 				    bool road, bool *road_near,
4314 				    bool hider, bool *hider_near)
4315 {
4316   struct drawn_sprite *saved_sprs = sprs;
4317   int i;
4318   int extra_idx = extra_index(pextra);
4319 
4320   if (is_cardinal_only_road(pextra)) {
4321     return 0;
4322   }
4323 
4324   /* Roads going diagonally adjacent to this tile need to be
4325    * partly drawn on this tile. */
4326 
4327   /* Draw the corner sprite if:
4328    *   - There is a diagonal road (not rail!) between two adjacent tiles.
4329    *   - There is no diagonal road (not rail!) that intersects this road.
4330    * The logic is simple: roads are drawn underneath railrods, but are
4331    * not always covered by them (even in the corners!).  But if a railroad
4332    * connects two tiles, only the railroad (no road) is drawn between
4333    * those tiles.
4334    */
4335   for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4336     enum direction8 dir = t->valid_tileset_dirs[i];
4337 
4338     if (!is_cardinal_tileset_dir(t, dir)) {
4339       /* Draw corner sprites for this non-cardinal direction. */
4340       int cw = (i + 1) % t->num_valid_tileset_dirs;
4341       int ccw
4342 	= (i + t->num_valid_tileset_dirs - 1) % t->num_valid_tileset_dirs;
4343       enum direction8 cwdir = t->valid_tileset_dirs[cw];
4344       enum direction8 ccwdir = t->valid_tileset_dirs[ccw];
4345 
4346       if (t->sprites.extras[extra_idx].u.road.corner[dir]
4347           && (road_near[cwdir] && road_near[ccwdir]
4348               && !(hider_near[cwdir] && hider_near[ccwdir]))
4349           && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
4350         ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.corner[dir]);
4351       }
4352     }
4353   }
4354 
4355   return sprs - saved_sprs;
4356 }
4357 
4358 /**************************************************************************
4359   Fill all road and rail sprites into the sprite array.
4360 **************************************************************************/
fill_road_sprite_array(const struct tileset * t,const struct extra_type * pextra,struct drawn_sprite * sprs,bv_extras textras,bv_extras * textras_near,struct terrain * tterrain_near[8],const struct city * pcity)4361 static int fill_road_sprite_array(const struct tileset *t,
4362                                   const struct extra_type *pextra,
4363                                   struct drawn_sprite *sprs,
4364                                   bv_extras textras,
4365                                   bv_extras *textras_near,
4366                                   struct terrain *tterrain_near[8],
4367                                   const struct city *pcity)
4368 {
4369   struct drawn_sprite *saved_sprs = sprs;
4370   bool road, road_near[8], hider, hider_near[8];
4371   bool land_near[8], hland_near[8];
4372   bool draw_road[8], draw_single_road;
4373   enum direction8 dir;
4374   int extra_idx = -1;
4375   bool cl = FALSE;
4376   enum extrastyle_id extrastyle;
4377   const struct road_type *proad = extra_road_get(pextra);
4378 
4379   extra_idx = extra_index(pextra);
4380 
4381   extrastyle = t->sprites.extras[extra_idx].extrastyle;
4382 
4383   if (extra_has_flag(pextra, EF_CONNECT_LAND)) {
4384     cl = TRUE;
4385   } else {
4386     int i;
4387 
4388     for (i = 0; i < 8; i++) {
4389       land_near[i] = FALSE;
4390     }
4391   }
4392 
4393   /* Fill some data arrays. rail_near and road_near store whether road/rail
4394    * is present in the given direction.  draw_rail and draw_road store
4395    * whether road/rail is to be drawn in that direction.  draw_single_road
4396    * and draw_single_rail store whether we need an isolated road/rail to be
4397    * drawn. */
4398   road = BV_ISSET(textras, extra_idx);
4399 
4400   hider = FALSE;
4401   extra_type_list_iterate(pextra->hiders, phider) {
4402     if (BV_ISSET(textras, extra_index(phider))) {
4403       hider = TRUE;
4404       break;
4405     }
4406   } extra_type_list_iterate_end;
4407 
4408   if (road && (!pcity || !gui_options.draw_cities) && !hider) {
4409     draw_single_road = TRUE;
4410   } else {
4411     draw_single_road = FALSE;
4412   }
4413 
4414   for (dir = 0; dir < 8; dir++) {
4415     bool roads_exist;
4416 
4417     /* Check if there is adjacent road/rail. */
4418     if (!is_cardinal_only_road(pextra)
4419         || is_cardinal_tileset_dir(t, dir)) {
4420       road_near[dir] = FALSE;
4421       extra_type_list_iterate(proad->integrators, iextra) {
4422         if (BV_ISSET(textras_near[dir], extra_index(iextra))) {
4423           road_near[dir] = TRUE;
4424           break;
4425         }
4426       } extra_type_list_iterate_end;
4427       if (cl) {
4428         land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
4429                           && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN);
4430       }
4431     } else {
4432       road_near[dir] = FALSE;
4433       land_near[dir] = FALSE;
4434     }
4435 
4436     /* Draw rail/road if there is a connection from this tile to the
4437      * adjacent tile.  But don't draw road if there is also a rail
4438      * connection. */
4439     roads_exist = road && (road_near[dir] || land_near[dir]);
4440     draw_road[dir] = roads_exist;
4441     hider_near[dir] = FALSE;
4442     hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
4443       && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN;
4444     extra_type_list_iterate(pextra->hiders, phider) {
4445       bool hider_dir = FALSE;
4446       bool land_dir = FALSE;
4447 
4448       if (!is_cardinal_only_road(phider)
4449           || is_cardinal_tileset_dir(t, dir)) {
4450         if (BV_ISSET(textras_near[dir], extra_index(phider))) {
4451           hider_near[dir] = TRUE;
4452           hider_dir = TRUE;
4453         }
4454         if (hland_near[dir]
4455             && is_extra_caused_by(phider, EC_ROAD)
4456             && extra_has_flag(phider, EF_CONNECT_LAND)) {
4457           land_dir = TRUE;
4458         }
4459         if (hider_dir || land_dir) {
4460           if (BV_ISSET(textras, extra_index(phider))) {
4461             draw_road[dir] = FALSE;
4462           }
4463         }
4464       }
4465     } extra_type_list_iterate_end;
4466 
4467     /* Don't draw an isolated road/rail if there's any connection.
4468      * draw_single_road would be true in the first place only if start tile has road,
4469      * so it will have road connection with any adjacent road tile. We check from real
4470      * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
4471      * as latter can be FALSE when road is simply hidden by another one, and we don't want to
4472      * draw single road in that case either. */
4473     if (draw_single_road && road_near[dir]) {
4474       draw_single_road = FALSE;
4475     }
4476   }
4477 
4478   /* Draw road corners */
4479   sprs
4480     += fill_road_corner_sprites(t, pextra, sprs, road, road_near, hider, hider_near);
4481 
4482   if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
4483     /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
4484      * This means we only need a few sprites, but a lot of drawing is
4485      * necessary and it generally doesn't look very good. */
4486     int i;
4487 
4488     /* First draw roads under rails. */
4489     if (road) {
4490       for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4491 	if (draw_road[t->valid_tileset_dirs[i]]) {
4492 	  ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.dir[i]);
4493 	}
4494       }
4495     }
4496   } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4497     /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
4498      * road connections, one sprite for diagonal road connections.
4499      * This means we need about 4x more sprites than in style 0, but up to
4500      * 4x less drawing is needed.  The drawing quality may also be
4501      * improved. */
4502 
4503     /* First draw roads under rails. */
4504     if (road) {
4505       int road_even_tileno = 0, road_odd_tileno = 0, i;
4506 
4507       for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
4508 	enum direction8 even = t->valid_tileset_dirs[2 * i];
4509 	enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
4510 
4511 	if (draw_road[even]) {
4512 	  road_even_tileno |= 1 << i;
4513 	}
4514 	if (draw_road[odd]) {
4515 	  road_odd_tileno |= 1 << i;
4516 	}
4517       }
4518 
4519       /* Draw the cardinal/even roads first. */
4520       if (road_even_tileno != 0) {
4521 	ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.even[road_even_tileno]);
4522       }
4523       if (road_odd_tileno != 0) {
4524 	ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.odd[road_odd_tileno]);
4525       }
4526     }
4527   } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4528     /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
4529      * entire finished tiles, with a bitwise index of the presence of
4530      * roads in each direction. */
4531 
4532     /* Draw roads first */
4533     if (road) {
4534       int road_tileno = 0, i;
4535 
4536       for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4537         enum direction8 vdir = t->valid_tileset_dirs[i];
4538 
4539         if (draw_road[vdir]) {
4540           road_tileno |= 1 << i;
4541         }
4542       }
4543 
4544       if (road_tileno != 0 || draw_single_road) {
4545         ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.total[road_tileno]);
4546       }
4547     }
4548   } else {
4549     fc_assert(FALSE);
4550   }
4551 
4552   /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
4553      ESTYLE_ROAD_PARITY_COMBINED only). */
4554   if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4555       || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4556     if (draw_single_road) {
4557       ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.isolated);
4558     }
4559   }
4560 
4561   return sprs - saved_sprs;
4562 }
4563 
4564 /**************************************************************************
4565   Return the index of the sprite to be used for irrigation or farmland in
4566   this tile.
4567 
4568   We assume that the current tile has farmland or irrigation.  We then
4569   choose a sprite (index) based upon which cardinally adjacent tiles have
4570   either farmland or irrigation (the two are considered interchangable for
4571   this).
4572 **************************************************************************/
get_irrigation_index(const struct tileset * t,struct extra_type * pextra,bv_extras * textras_near)4573 static int get_irrigation_index(const struct tileset *t,
4574                                 struct extra_type *pextra,
4575                                 bv_extras *textras_near)
4576 {
4577   int tileno = 0, i;
4578 
4579   for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4580     enum direction8 dir = t->cardinal_tileset_dirs[i];
4581 
4582     if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
4583       tileno |= 1 << i;
4584     }
4585   }
4586 
4587   return tileno;
4588 }
4589 
4590 /**************************************************************************
4591   Fill in the farmland/irrigation sprite for the tile.
4592 **************************************************************************/
fill_irrigation_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,bv_extras textras,bv_extras * textras_near,const struct city * pcity)4593 static int fill_irrigation_sprite_array(const struct tileset *t,
4594                                         struct drawn_sprite *sprs,
4595                                         bv_extras textras,
4596                                         bv_extras *textras_near,
4597                                         const struct city *pcity)
4598 {
4599   struct drawn_sprite *saved_sprs = sprs;
4600 
4601   /* We don't draw the irrigation if there's a city (it just gets overdrawn
4602    * anyway, and ends up looking bad). */
4603   if (!(pcity && gui_options.draw_cities)) {
4604     extra_type_list_iterate(t->style_lists[ESTYLE_CARDINALS], pextra) {
4605       if (is_extra_drawing_enabled(pextra)) {
4606         int eidx = extra_index(pextra);
4607 
4608         if (BV_ISSET(textras, eidx)) {
4609           bool hidden = FALSE;
4610 
4611           extra_type_list_iterate(pextra->hiders, phider) {
4612             if (BV_ISSET(textras, extra_index(phider))) {
4613               hidden = TRUE;
4614               break;
4615             }
4616           } extra_type_list_iterate_end;
4617 
4618           if (!hidden) {
4619             int idx = get_irrigation_index(t, pextra, textras_near);
4620 
4621             ADD_SPRITE_SIMPLE(t->sprites.extras[eidx].u.cardinals[idx]);
4622           }
4623         }
4624       }
4625     } extra_type_list_iterate_end;
4626   }
4627 
4628   return sprs - saved_sprs;
4629 }
4630 
4631 /**************************************************************************
4632   Fill in the city overlays for the tile.  This includes the citymap
4633   overlays on the mapview as well as the tile output sprites.
4634 **************************************************************************/
fill_city_overlays_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct city * citymode)4635 static int fill_city_overlays_sprite_array(const struct tileset *t,
4636 					   struct drawn_sprite *sprs,
4637 					   const struct tile *ptile,
4638 					   const struct city *citymode)
4639 {
4640   const struct city *pcity;
4641   const struct city *pwork;
4642   struct unit *psettler;
4643   struct drawn_sprite *saved_sprs = sprs;
4644   int city_x, city_y;
4645   const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
4646 
4647   if (NULL == ptile || TILE_UNKNOWN == client_tile_get_known(ptile)) {
4648     return 0;
4649   }
4650   pwork = tile_worked(ptile);
4651 
4652   if (citymode) {
4653     pcity = citymode;
4654   } else {
4655     pcity = find_city_or_settler_near_tile(ptile, &psettler);
4656   }
4657 
4658   /* Below code does not work if pcity is invisible.
4659    * Make sure it is not. */
4660   fc_assert_ret_val(pcity == NULL || pcity->tile != NULL, 0);
4661   if (pcity && !pcity->tile) {
4662     pcity = NULL;
4663   }
4664 
4665   if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
4666     /* FIXME: check elsewhere for valid tile (instead of above) */
4667 
4668     if (!citymode && pcity->client.colored) {
4669       /* Add citymap overlay for a city. */
4670       int idx = pcity->client.color_index % NUM_CITY_COLORS;
4671 
4672       if (NULL != pwork && pwork == pcity) {
4673         ADD_SPRITE_SIMPLE(t->sprites.city.worked_tile_overlay.p[idx]);
4674       } else if (city_can_work_tile(pcity, ptile)) {
4675         ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4676       }
4677     } else if (NULL != pwork && pwork == pcity
4678                && (citymode || gui_options.draw_city_output)) {
4679 
4680       /* Add on the tile output sprites.
4681        * NOTE: To show correct output on end of turn
4682        * base_city_celebrating() must be used instead of city_celebrating()
4683        * mirroring the behavior of the server that does so in
4684        * city_tile_cache_update(). */
4685       bool celebrating = base_city_celebrating(pcity);
4686       int food = city_tile_output(pcity, ptile, celebrating, O_FOOD);
4687       int shields = city_tile_output(pcity, ptile, celebrating, O_SHIELD);
4688       int trade = city_tile_output(pcity, ptile, celebrating, O_TRADE);
4689 
4690       const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
4691       const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
4692 
4693       food = CLIP(0, food, NUM_TILES_DIGITS - 1);
4694       shields = CLIP(0, shields, NUM_TILES_DIGITS - 1);
4695       trade = CLIP(0, trade, NUM_TILES_DIGITS - 1);
4696 
4697       ADD_SPRITE(t->sprites.city.tile_foodnum[food], TRUE, ox, oy);
4698       ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
4699       ADD_SPRITE(t->sprites.city.tile_tradenum[trade], TRUE, ox, oy);
4700     }
4701   } else if (psettler && psettler->client.colored) {
4702     /* Add citymap overlay for a unit. */
4703     int idx = psettler->client.color_index % NUM_CITY_COLORS;
4704 
4705     ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4706   }
4707 
4708   return sprs - saved_sprs;
4709 }
4710 
4711 /****************************************************************************
4712   Helper function for fill_terrain_sprite_layer.
4713   Fill in the sprite array for blended terrain.
4714 ****************************************************************************/
fill_terrain_sprite_blending(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near)4715 static int fill_terrain_sprite_blending(const struct tileset *t,
4716 					struct drawn_sprite *sprs,
4717 					const struct tile *ptile,
4718 					const struct terrain *pterrain,
4719 					struct terrain **tterrain_near)
4720 {
4721   struct drawn_sprite *saved_sprs = sprs;
4722   const int W = t->normal_tile_width, H = t->normal_tile_height;
4723   const int offsets[4][2] = {
4724     {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4725   };
4726   enum direction4 dir = 0;
4727 
4728   /*
4729    * We want to mark unknown tiles so that an unreal tile will be
4730    * given the same marking as our current tile - that way we won't
4731    * get the "unknown" dither along the edge of the map.
4732    */
4733   for (; dir < 4; dir++) {
4734     struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
4735     struct terrain *other;
4736 
4737     if (!tile1
4738 	|| client_tile_get_known(tile1) == TILE_UNKNOWN
4739 	|| pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
4740 	|| (0 == t->sprites.drawing[terrain_index(other)]->blending
4741 	   &&  NULL == t->sprites.drawing[terrain_index(other)]->blender)) {
4742       continue;
4743     }
4744 
4745     ADD_SPRITE(t->sprites.drawing[terrain_index(other)]->blend[dir], TRUE,
4746                offsets[dir][0], offsets[dir][1]);
4747   }
4748 
4749   return sprs - saved_sprs;
4750 }
4751 
4752 /****************************************************************************
4753   Add sprites for fog (and some forms of darkness).
4754 ****************************************************************************/
fill_fog_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner)4755 static int fill_fog_sprite_array(const struct tileset *t,
4756 				 struct drawn_sprite *sprs,
4757 				 const struct tile *ptile,
4758 				 const struct tile_edge *pedge,
4759 				 const struct tile_corner *pcorner)
4760 {
4761   struct drawn_sprite *saved_sprs = sprs;
4762 
4763   if (t->fogstyle == FOG_SPRITE && gui_options.draw_fog_of_war
4764       && NULL != ptile
4765       && TILE_KNOWN_UNSEEN == client_tile_get_known(ptile)) {
4766     /* With FOG_AUTO, fog is done this way. */
4767     ADD_SPRITE_SIMPLE(t->sprites.tx.fog);
4768   }
4769 
4770   if (t->darkness_style == DARKNESS_CORNER && pcorner
4771       && gui_options.draw_fog_of_war) {
4772     int i, tileno = 0;
4773 
4774     for (i = 3; i >= 0; i--) {
4775       const int unknown = 0, fogged = 1, known = 2;
4776       int value = -1;
4777 
4778       if (!pcorner->tile[i]) {
4779 	value = fogged;
4780       } else {
4781 	switch (client_tile_get_known(pcorner->tile[i])) {
4782 	case TILE_KNOWN_SEEN:
4783 	  value = known;
4784 	  break;
4785 	case TILE_KNOWN_UNSEEN:
4786 	  value = fogged;
4787 	  break;
4788 	case TILE_UNKNOWN:
4789 	  value = unknown;
4790 	  break;
4791 	}
4792       }
4793       fc_assert(value >= 0 && value < 3);
4794 
4795       tileno = tileno * 3 + value;
4796     }
4797 
4798     if (t->sprites.tx.fullfog[tileno]) {
4799       ADD_SPRITE_SIMPLE(t->sprites.tx.fullfog[tileno]);
4800     }
4801   }
4802 
4803   return sprs - saved_sprs;
4804 }
4805 
4806 /****************************************************************************
4807   Helper function for fill_terrain_sprite_layer.
4808 ****************************************************************************/
fill_terrain_sprite_array(struct tileset * t,struct drawn_sprite * sprs,int l,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near,struct drawing_data * draw)4809 static int fill_terrain_sprite_array(struct tileset *t,
4810 				     struct drawn_sprite *sprs,
4811 				     int l, /* layer_num */
4812 				     const struct tile *ptile,
4813 				     const struct terrain *pterrain,
4814 				     struct terrain **tterrain_near,
4815 				     struct drawing_data *draw)
4816 {
4817   struct drawn_sprite *saved_sprs = sprs;
4818   struct drawing_layer *dlp = &draw->layer[l];
4819   int this = dlp->match_index[0];
4820   int that = dlp->match_index[1];
4821   int ox = dlp->offset_x;
4822   int oy = dlp->offset_y;
4823   int i;
4824 
4825 #define MATCH(dir)							    \
4826     (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l	    \
4827      ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4828      : -1)
4829 
4830   switch (dlp->sprite_type) {
4831   case CELL_WHOLE:
4832     {
4833       switch (dlp->match_style) {
4834       case MATCH_NONE:
4835 	{
4836 	  int count = sprite_vector_size(&dlp->base);
4837 
4838 	  if (count > 0) {
4839             /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4840              * to limit the number to a handleable size [0..32000). */
4841             count = fc_randomly(tile_index(ptile) % 32000, count);
4842 
4843 	    if (dlp->is_tall) {
4844 	      ox += FULL_TILE_X_OFFSET;
4845 	      oy += FULL_TILE_Y_OFFSET;
4846 	    }
4847 	    ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
4848 	  }
4849 	  break;
4850 	}
4851       case MATCH_SAME:
4852 	{
4853 	  int tileno = 0;
4854 
4855 	  for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4856 	    enum direction8 dir = t->cardinal_tileset_dirs[i];
4857 
4858 	    if (MATCH(dir) == this) {
4859 	      tileno |= 1 << i;
4860 	    }
4861 	  }
4862 
4863 	  if (dlp->is_tall) {
4864 	    ox += FULL_TILE_X_OFFSET;
4865 	    oy += FULL_TILE_Y_OFFSET;
4866 	  }
4867 	  ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
4868 	  break;
4869 	}
4870       case MATCH_PAIR:
4871       case MATCH_FULL:
4872         fc_assert(FALSE); /* not yet defined */
4873         break;
4874       };
4875       break;
4876     }
4877   case CELL_CORNER:
4878     {
4879       /* Divide the tile up into four rectangular cells.  Each of these
4880        * cells covers one corner, and each is adjacent to 3 different
4881        * tiles.  For each cell we pick a sprite based upon the adjacent
4882        * terrains at each of those tiles.  Thus, we have 8 different sprites
4883        * for each of the 4 cells (32 sprites total).
4884        *
4885        * These arrays correspond to the direction4 ordering. */
4886       const int W = t->normal_tile_width;
4887       const int H = t->normal_tile_height;
4888       const int iso_offsets[4][2] = {
4889 	{W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
4890       };
4891       const int noniso_offsets[4][2] = {
4892 	{0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
4893       };
4894 
4895       /* put corner cells */
4896       for (i = 0; i < NUM_CORNER_DIRS; i++) {
4897 	const int count = dlp->match_indices;
4898 	int array_index = 0;
4899 	enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
4900 	int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
4901 	int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
4902 	int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
4903 	struct sprite *s;
4904 
4905 	/* synthesize 4 dimensional array? */
4906 	switch (dlp->match_style) {
4907 	case MATCH_NONE:
4908 	  /* We have no need for matching, just plug the piece in place. */
4909 	  break;
4910 	case MATCH_SAME:
4911 	  array_index = array_index * 2 + (m[2] != this);
4912 	  array_index = array_index * 2 + (m[1] != this);
4913 	  array_index = array_index * 2 + (m[0] != this);
4914 	  break;
4915 	case MATCH_PAIR:
4916 	  array_index = array_index * 2 + (m[2] == that);
4917 	  array_index = array_index * 2 + (m[1] == that);
4918 	  array_index = array_index * 2 + (m[0] == that);
4919 	  break;
4920 	case MATCH_FULL:
4921 	default:
4922 	  {
4923 	    int n[3];
4924 	    int j = 0;
4925 	    for (; j < 3; j++) {
4926 	      int k = 0;
4927 	      for (; k < count; k++) {
4928 		n[j] = k; /* default to last entry */
4929 		if (m[j] == dlp->match_index[k])
4930 		{
4931 		  break;
4932 		}
4933 	      }
4934 	    }
4935 	    array_index = array_index * count + n[2];
4936 	    array_index = array_index * count + n[1];
4937 	    array_index = array_index * count + n[0];
4938 	  }
4939 	  break;
4940 	};
4941 	array_index = array_index * NUM_CORNER_DIRS + i;
4942 
4943 	s = dlp->cells[array_index];
4944 	if (s) {
4945 	  ADD_SPRITE(s, TRUE, x, y);
4946 	}
4947       }
4948       break;
4949     }
4950   };
4951 #undef MATCH
4952 
4953   return sprs - saved_sprs;
4954 }
4955 
4956 /****************************************************************************
4957   Helper function for fill_terrain_sprite_layer.
4958   Fill in the sprite array of darkness.
4959 ****************************************************************************/
fill_terrain_sprite_darkness(struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,struct terrain ** tterrain_near)4960 static int fill_terrain_sprite_darkness(struct tileset *t,
4961 				     struct drawn_sprite *sprs,
4962 				     const struct tile *ptile,
4963 				     struct terrain **tterrain_near)
4964 {
4965   struct drawn_sprite *saved_sprs = sprs;
4966   int i, tileno;
4967   struct tile *adjc_tile;
4968 
4969 #define UNKNOWN(dir)                                        \
4970     ((adjc_tile = mapstep(ptile, (dir)))		    \
4971      && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4972 
4973   switch (t->darkness_style) {
4974   case DARKNESS_NONE:
4975     break;
4976   case DARKNESS_ISORECT:
4977     for (i = 0; i < 4; i++) {
4978       const int W = t->normal_tile_width, H = t->normal_tile_height;
4979       int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
4980 
4981       if (UNKNOWN(DIR4_TO_DIR8[i])) {
4982 	ADD_SPRITE(t->sprites.tx.darkness[i], TRUE,
4983 		   offsets[i][0], offsets[i][1]);
4984       }
4985     }
4986     break;
4987   case DARKNESS_CARD_SINGLE:
4988     for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4989       if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4990 	ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[i]);
4991       }
4992     }
4993     break;
4994   case DARKNESS_CARD_FULL:
4995     /* We're looking to find the INDEX_NSEW for the directions that
4996      * are unknown.  We want to mark unknown tiles so that an unreal
4997      * tile will be given the same marking as our current tile - that
4998      * way we won't get the "unknown" dither along the edge of the
4999      * map. */
5000     tileno = 0;
5001     for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5002       if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5003 	tileno |= 1 << i;
5004       }
5005     }
5006 
5007     if (tileno != 0) {
5008       ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[tileno]);
5009     }
5010     break;
5011   case DARKNESS_CORNER:
5012     /* Handled separately. */
5013     break;
5014   };
5015 #undef UNKNOWN
5016 
5017   return sprs - saved_sprs;
5018 }
5019 
5020 /****************************************************************************
5021   Add sprites for the base tile to the sprite list.  This doesn't
5022   include specials or rivers.
5023 ****************************************************************************/
fill_terrain_sprite_layer(struct tileset * t,struct drawn_sprite * sprs,int layer_num,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near)5024 static int fill_terrain_sprite_layer(struct tileset *t,
5025 				     struct drawn_sprite *sprs,
5026 				     int layer_num,
5027 				     const struct tile *ptile,
5028 				     const struct terrain *pterrain,
5029 				     struct terrain **tterrain_near)
5030 {
5031   struct sprite *sprite;
5032   struct drawn_sprite *saved_sprs = sprs;
5033   struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
5034   const int l = (draw->is_reversed
5035 		 ? (draw->num_layers - layer_num - 1) : layer_num);
5036 
5037   fc_assert(layer_num < TERRAIN_LAYER_COUNT);
5038 
5039   /* Skip the normal drawing process. */
5040   /* FIXME: this should avoid calling load_sprite since it's slow and
5041    * increases the refcount without limit. */
5042   if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite,
5043                                                   TRUE, FALSE))) {
5044     if (l == 0) {
5045       ADD_SPRITE_SIMPLE(sprite);
5046       return 1;
5047     } else {
5048       return 0;
5049     }
5050   }
5051 
5052   if (l < draw->num_layers) {
5053     sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
5054 
5055     if ((l + 1) == draw->blending) {
5056       sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
5057     }
5058   }
5059 
5060   /* Add darkness on top of the designed terrain layer. Note that darkness is always
5061    * drawn, even in citymode, etc. */
5062   if (layer_num == t->darkness_layer) {
5063     sprs += fill_terrain_sprite_darkness(t, sprs, ptile, tterrain_near);
5064   }
5065 
5066   return sprs - saved_sprs;
5067 }
5068 
5069 /****************************************************************************
5070   Indicate whether a unit is to be drawn with a surrounding city outline
5071   under current conditions.
5072   (This includes being in focus, but if the caller has already checked that,
5073   they can bypass this slightly expensive check with check_focus == FALSE.)
5074 ****************************************************************************/
unit_drawn_with_city_outline(const struct unit * punit,bool check_focus)5075 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
5076 {
5077   /* Display an outline for city-builder type units if they are selected,
5078    * and on a tile where a city can be built.
5079    * But suppress the outline if the unit has orders (likely it is in
5080    * transit to somewhere else and this will just slow down redraws). */
5081   return gui_options.draw_city_outlines
5082          && unit_is_cityfounder(punit)
5083          && !unit_has_orders(punit)
5084          && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN
5085              && city_can_be_built_here(unit_tile(punit), punit))
5086          && (!check_focus || unit_is_in_focus(punit));
5087 }
5088 
5089 /****************************************************************************
5090   Fill in the grid sprites for the given tile, city, and unit.
5091 ****************************************************************************/
fill_grid_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner,const struct unit * punit,const struct city * pcity,const struct city * citymode)5092 static int fill_grid_sprite_array(const struct tileset *t,
5093 				  struct drawn_sprite *sprs,
5094 				  const struct tile *ptile,
5095 				  const struct tile_edge *pedge,
5096 				  const struct tile_corner *pcorner,
5097 				  const struct unit *punit,
5098 				  const struct city *pcity,
5099 				  const struct city *citymode)
5100 {
5101   struct drawn_sprite *saved_sprs = sprs;
5102 
5103   if (pedge) {
5104     bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
5105     bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
5106     int i;
5107     struct unit_list *pfocus_units = get_units_in_focus();
5108 
5109     for (i = 0; i < NUM_EDGE_TILES; i++) {
5110       int dummy_x, dummy_y;
5111       const struct tile *tile = pedge->tile[i];
5112       struct player *powner = tile ? tile_owner(tile) : NULL;
5113 
5114       known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
5115       unit[i] = FALSE;
5116       if (tile && !citymode) {
5117         unit_list_iterate(pfocus_units, pfocus_unit) {
5118           if (unit_drawn_with_city_outline(pfocus_unit, FALSE)) {
5119             struct tile *utile = unit_tile(pfocus_unit);
5120             int radius = game.info.init_city_radius_sq
5121               + get_target_bonus_effects(NULL, unit_owner(pfocus_unit), NULL,
5122                                          NULL, NULL, utile, NULL, NULL,
5123                                          NULL, NULL,
5124                                          EFT_CITY_RADIUS_SQ);
5125 
5126             if (city_tile_to_city_map(&dummy_x, &dummy_y, radius,
5127                                       utile, tile)) {
5128               unit[i] = TRUE;
5129               break;
5130             }
5131           }
5132         } unit_list_iterate_end;
5133       }
5134       worked[i] = FALSE;
5135 
5136       city[i] = (tile
5137                  && (NULL == powner || NULL == client.conn.playing
5138                      || powner == client.conn.playing)
5139                  && player_in_city_map(client.conn.playing, tile));
5140       if (city[i]) {
5141 	if (citymode) {
5142 	  /* In citymode, we only draw worked tiles for this city - other
5143 	   * tiles may be marked as unavailable. */
5144 	  worked[i] = (tile_worked(tile) == citymode);
5145 	} else {
5146 	  worked[i] = (NULL != tile_worked(tile));
5147 	}
5148       }
5149     }
5150 
5151     if (mapdeco_is_highlight_set(pedge->tile[0])
5152         || mapdeco_is_highlight_set(pedge->tile[1])) {
5153       ADD_SPRITE_SIMPLE(t->sprites.grid.selected[pedge->type]);
5154     } else if (!gui_options.draw_terrain && gui_options.draw_coastline
5155 	       && pedge->tile[0] && pedge->tile[1]
5156 	       && known[0] && known[1]
5157 	       && (is_ocean_tile(pedge->tile[0])
5158 		   ^ is_ocean_tile(pedge->tile[1]))) {
5159       ADD_SPRITE_SIMPLE(t->sprites.grid.coastline[pedge->type]);
5160     } else {
5161       if (gui_options.draw_map_grid) {
5162         if (worked[0] || worked[1]) {
5163           ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5164         } else if (city[0] || city[1]) {
5165           ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5166         } else if (known[0] || known[1]) {
5167           ADD_SPRITE_SIMPLE(t->sprites.grid.main[pedge->type]);
5168         }
5169       }
5170       if (gui_options.draw_city_outlines) {
5171         if (XOR(city[0], city[1])) {
5172           ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5173         }
5174         if (XOR(unit[0], unit[1])) {
5175           ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5176         }
5177       }
5178     }
5179 
5180     if (gui_options.draw_borders
5181         && BORDERS_DISABLED != game.info.borders
5182         && known[0]
5183         && known[1]) {
5184       struct player *owner0 = tile_owner(pedge->tile[0]);
5185       struct player *owner1 = tile_owner(pedge->tile[1]);
5186 
5187       if (owner0 != owner1) {
5188         if (owner0) {
5189           int plrid = player_index(owner0);
5190           ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5191                             [pedge->type][0]);
5192         }
5193         if (owner1) {
5194           int plrid = player_index(owner1);
5195           ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5196                             [pedge->type][1]);
5197         }
5198       }
5199     }
5200   } else if (NULL != ptile && TILE_UNKNOWN != client_tile_get_known(ptile)) {
5201     int cx, cy;
5202 
5203     if (citymode
5204         /* test to ensure valid coordinates? */
5205         && city_base_to_city_map(&cx, &cy, citymode, ptile)
5206         && !client_city_can_work_tile(citymode, ptile)) {
5207       ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5208     }
5209 
5210     if (gui_options.draw_native && citymode == NULL) {
5211       bool native = TRUE;
5212       struct unit_list *pfocus_units = get_units_in_focus();
5213 
5214       unit_list_iterate(pfocus_units, pfocus) {
5215         if (!is_native_tile(unit_type_get(pfocus), ptile)) {
5216           native = FALSE;
5217           break;
5218         }
5219       } unit_list_iterate_end;
5220 
5221       if (!native) {
5222         if (t->sprites.grid.nonnative != NULL) {
5223           ADD_SPRITE_SIMPLE(t->sprites.grid.nonnative);
5224         } else {
5225           ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5226         }
5227       }
5228     }
5229   }
5230 
5231   return sprs - saved_sprs;
5232 }
5233 
5234 /****************************************************************************
5235   Fill in the given sprite array with any needed goto sprites.
5236 ****************************************************************************/
fill_goto_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner)5237 static int fill_goto_sprite_array(const struct tileset *t,
5238 				  struct drawn_sprite *sprs,
5239 				  const struct tile *ptile,
5240 				  const struct tile_edge *pedge,
5241 				  const struct tile_corner *pcorner)
5242 {
5243   struct drawn_sprite *saved_sprs = sprs;
5244   struct sprite *sprite;
5245   bool warn = FALSE;
5246   enum goto_tile_state state;
5247   int length;
5248   bool waypoint;
5249 
5250   if (goto_tile_state(ptile, &state, &length, &waypoint)) {
5251     if (length >= 0) {
5252       fc_assert(state >= 0);
5253       fc_assert(state < ARRAY_SIZE(t->sprites.path.s));
5254 
5255       sprite = t->sprites.path.s[state].specific;
5256       if (sprite != NULL) {
5257         ADD_SPRITE(sprite, FALSE, 0, 0);
5258       }
5259 
5260       sprite = t->sprites.path.s[state].turns[length % 10];
5261       ADD_SPRITE_SIMPLE(sprite);
5262       if (length >= 10) {
5263         sprite = t->sprites.path.s[state].turns_tens[(length / 10) % 10];
5264         ADD_SPRITE_SIMPLE(sprite);
5265         if (length >= 100) {
5266           sprite = t->sprites.path.s[state].turns_hundreds[(length / 100)
5267                                                            % 10];
5268 
5269           if (sprite != NULL) {
5270             ADD_SPRITE_SIMPLE(sprite);
5271             if (length >= 1000) {
5272               warn = TRUE;
5273             }
5274           } else {
5275             warn = TRUE;
5276           }
5277         }
5278       }
5279     }
5280 
5281     if (waypoint) {
5282       ADD_SPRITE(t->sprites.path.waypoint, FALSE, 0, 0);
5283     }
5284 
5285     if (warn) {
5286       /* Warn only once by tileset. */
5287       static char last_reported[256] = "";
5288 
5289       if (0 != strcmp(last_reported, t->name)) {
5290         log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5291                      "such as %d. Path not displayed as expected."),
5292                    t->name, length);
5293         sz_strlcpy(last_reported, t->name);
5294       }
5295     }
5296   }
5297 
5298   return sprs - saved_sprs;
5299 }
5300 
5301 /****************************************************************************
5302   Should the given extra be drawn
5303 ****************************************************************************/
is_extra_drawing_enabled(struct extra_type * pextra)5304 static bool is_extra_drawing_enabled(struct extra_type *pextra)
5305 {
5306   bool no_disable = TRUE; /* Draw if matches no cause */
5307 
5308   if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
5309     if (gui_options.draw_irrigation) {
5310       return TRUE;
5311     }
5312     no_disable = FALSE;
5313   }
5314   if (is_extra_caused_by(pextra, EC_POLLUTION)
5315       || is_extra_caused_by(pextra, EC_FALLOUT)) {
5316     if (gui_options.draw_pollution) {
5317       return TRUE;
5318     }
5319     no_disable = FALSE;
5320   }
5321   if (is_extra_caused_by(pextra, EC_MINE)) {
5322     if (gui_options.draw_mines) {
5323       return TRUE;
5324     }
5325     no_disable = FALSE;
5326   }
5327   if (is_extra_caused_by(pextra, EC_HUT)) {
5328     if (gui_options.draw_huts) {
5329       return TRUE;
5330     }
5331     no_disable = FALSE;
5332   }
5333   if (is_extra_caused_by(pextra, EC_BASE)) {
5334     if (gui_options.draw_fortress_airbase) {
5335       return TRUE;
5336     }
5337     no_disable = FALSE;
5338   }
5339   if (is_extra_caused_by(pextra, EC_ROAD)) {
5340     if (gui_options.draw_roads_rails) {
5341       return TRUE;
5342     }
5343     no_disable = FALSE;
5344   }
5345 
5346   return no_disable;
5347 }
5348 
5349 /****************************************************************************
5350   Fill in the sprite array for the given tile, city, and unit.
5351 
5352   ptile, if specified, gives the tile.  If specified the terrain and specials
5353   will be drawn for this tile.  In this case (map_x,map_y) should give the
5354   location of the tile.
5355 
5356   punit, if specified, gives the unit.  For tile drawing this should
5357   generally be get_drawable_unit(); otherwise it can be any unit.
5358 
5359   pcity, if specified, gives the city.  For tile drawing this should
5360   generally be tile_city(ptile); otherwise it can be any city.
5361 
5362   citymode specifies whether this is part of a citydlg.  If so some drawing
5363   is done differently.
5364 ****************************************************************************/
fill_sprite_array(struct tileset * t,struct drawn_sprite * sprs,enum mapview_layer layer,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner,const struct unit * punit,const struct city * pcity,const struct city * citymode,const struct unit_type * putype)5365 int fill_sprite_array(struct tileset *t,
5366                       struct drawn_sprite *sprs, enum mapview_layer layer,
5367                       const struct tile *ptile,
5368                       const struct tile_edge *pedge,
5369                       const struct tile_corner *pcorner,
5370                       const struct unit *punit, const struct city *pcity,
5371                       const struct city *citymode,
5372                       const struct unit_type *putype)
5373 {
5374   int tileno, dir;
5375   bv_extras textras_near[8];
5376   bv_extras textras;
5377   struct terrain *tterrain_near[8];
5378   struct terrain *pterrain = NULL;
5379   struct drawn_sprite *save_sprs = sprs;
5380   struct player *owner = NULL;
5381   /* Unit drawing is disabled when the view options are turned off,
5382    * but only where we're drawing on the mapview. */
5383   bool do_draw_unit = (punit && (gui_options.draw_units || !ptile
5384 				 || (gui_options.draw_focus_unit
5385 				     && unit_is_in_focus(punit))));
5386   bool solid_bg = (gui_options.solid_color_behind_units
5387 		   && (do_draw_unit
5388 		       || (pcity && gui_options.draw_cities)
5389 		       || (ptile && !gui_options.draw_terrain)));
5390 
5391   if (citymode) {
5392     int count = 0, i, cx, cy;
5393     const struct tile *const *tiles = NULL;
5394     bool valid = FALSE;
5395 
5396     if (ptile) {
5397       tiles = &ptile;
5398       count = 1;
5399     } else if (pcorner) {
5400       tiles = pcorner->tile;
5401       count = NUM_CORNER_TILES;
5402     } else if (pedge) {
5403       tiles = pedge->tile;
5404       count = NUM_EDGE_TILES;
5405     }
5406 
5407     for (i = 0; i < count; i++) {
5408       if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
5409 	valid = TRUE;
5410 	break;
5411       }
5412     }
5413     if (!valid) {
5414       return 0;
5415     }
5416   }
5417 
5418   if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
5419     textras = *tile_extras(ptile);
5420     pterrain = tile_terrain(ptile);
5421 
5422     if (NULL != pterrain) {
5423       if (layer == LAYER_TERRAIN1
5424           || layer == LAYER_TERRAIN2
5425           || layer == LAYER_TERRAIN3
5426           || layer == LAYER_WATER
5427           || layer == LAYER_ROADS) {
5428         build_tile_data(ptile, pterrain, tterrain_near, textras_near);
5429       }
5430     } else {
5431       log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
5432                 TILE_XY(ptile));
5433     }
5434   } else {
5435     BV_CLR_ALL(textras);
5436   }
5437 
5438   switch (layer) {
5439   case LAYER_BACKGROUND:
5440     /* Set up background color. */
5441     if (gui_options.solid_color_behind_units) {
5442       if (do_draw_unit) {
5443 	owner = unit_owner(punit);
5444       } else if (pcity && gui_options.draw_cities) {
5445 	owner = city_owner(pcity);
5446       }
5447     }
5448     if (owner) {
5449       ADD_SPRITE_SIMPLE(t->sprites.player[player_index(owner)].background);
5450     } else if (ptile && !gui_options.draw_terrain) {
5451       ADD_SPRITE_SIMPLE(t->sprites.background.graphic);
5452     }
5453     break;
5454 
5455   case LAYER_TERRAIN1:
5456     if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5457       sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
5458     }
5459     break;
5460 
5461   case LAYER_TERRAIN2:
5462     if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5463       sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
5464     }
5465     break;
5466 
5467   case LAYER_TERRAIN3:
5468     if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5469       fc_assert(MAX_NUM_LAYERS == 3);
5470       sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
5471     }
5472     break;
5473 
5474   case LAYER_WATER:
5475     if (NULL != pterrain) {
5476       if (gui_options.draw_terrain && !solid_bg
5477           && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
5478 	for (dir = 0; dir < t->num_cardinal_tileset_dirs; dir++) {
5479           int didx = t->cardinal_tileset_dirs[dir];
5480 
5481           extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5482             int idx = extra_index(priver);
5483 
5484             if (BV_ISSET(textras_near[didx], idx)) {
5485               if (t->sprites.extras[idx].u.road.ru.rivers.outlet[dir] != NULL) {
5486                 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.outlet[dir]);
5487               }
5488               break;
5489             }
5490           } extra_type_list_iterate_end;
5491 	}
5492       }
5493 
5494       sprs += fill_irrigation_sprite_array(t, sprs, textras, textras_near,
5495 					   pcity);
5496 
5497       if (gui_options.draw_terrain && !solid_bg) {
5498         extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5499           int idx = extra_index(priver);
5500 
5501           if (BV_ISSET(textras, idx)) {
5502             int i;
5503 
5504             /* Draw rivers on top of irrigation. */
5505             tileno = 0;
5506             for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5507               enum direction8 cdir = t->cardinal_tileset_dirs[i];
5508 
5509               if (terrain_type_terrain_class(tterrain_near[cdir]) == TC_OCEAN
5510                   || BV_ISSET(textras_near[cdir], idx)) {
5511                 tileno |= 1 << i;
5512               }
5513             }
5514 
5515             ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[tileno]);
5516           }
5517         } extra_type_list_iterate_end;
5518       }
5519     }
5520     break;
5521 
5522   case LAYER_ROADS:
5523     if (NULL != pterrain) {
5524       extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_SEPARATE], pextra) {
5525         if (is_extra_drawing_enabled(pextra)) {
5526           sprs += fill_road_sprite_array(t, pextra, sprs,
5527                                          textras, textras_near,
5528                                          tterrain_near, pcity);
5529         }
5530       } extra_type_list_iterate_end;
5531       extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_PARITY_COMBINED], pextra) {
5532         if (is_extra_drawing_enabled(pextra)) {
5533           sprs += fill_road_sprite_array(t, pextra, sprs,
5534                                          textras, textras_near,
5535                                          tterrain_near, pcity);
5536         }
5537       } extra_type_list_iterate_end;
5538       extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_COMBINED], pextra) {
5539         if (is_extra_drawing_enabled(pextra)) {
5540           sprs += fill_road_sprite_array(t, pextra, sprs,
5541                                          textras, textras_near,
5542                                          tterrain_near, pcity);
5543         }
5544       } extra_type_list_iterate_end;
5545     }
5546     break;
5547 
5548   case LAYER_SPECIAL1:
5549     if (NULL != pterrain) {
5550       if (gui_options.draw_specials) {
5551 	if (tile_resource_is_valid(ptile)) {
5552 	  ADD_SPRITE_SIMPLE(t->sprites.resource[resource_index(tile_resource(ptile))]);
5553 	}
5554       }
5555 
5556       if (ptile) {
5557         extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5558           if (tile_has_extra(ptile, pextra)
5559               && is_extra_drawing_enabled(pextra)
5560               && t->sprites.extras[extra_index(pextra)].u.bmf.background) {
5561             bool hidden = FALSE;
5562 
5563             extra_type_list_iterate(pextra->hiders, phider) {
5564               if (BV_ISSET(textras, extra_index(phider))) {
5565                 hidden = TRUE;
5566                 break;
5567               }
5568             } extra_type_list_iterate_end;
5569 
5570             if (!hidden) {
5571               ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.background);
5572             }
5573           }
5574         } extra_type_list_iterate_end;
5575       }
5576 
5577       extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE1], pextra) {
5578         if (BV_ISSET(textras, extra_index(pextra))
5579             && is_extra_drawing_enabled(pextra)) {
5580           bool hidden = FALSE;
5581 
5582           extra_type_list_iterate(pextra->hiders, phider) {
5583             if (BV_ISSET(textras, extra_index(phider))) {
5584               hidden = TRUE;
5585               break;
5586             }
5587           } extra_type_list_iterate_end;
5588 
5589           if (!hidden) {
5590             ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5591           }
5592         }
5593       } extra_type_list_iterate_end;
5594     }
5595     break;
5596 
5597   case LAYER_GRID1:
5598     if (t->type == TS_ISOMETRIC) {
5599       sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5600 				     punit, pcity, citymode);
5601     }
5602     break;
5603 
5604   case LAYER_CITY1:
5605     /* City.  Some city sprites are drawn later. */
5606     if (pcity && gui_options.draw_cities) {
5607       if (!gui_options.draw_full_citybar && !gui_options.solid_color_behind_units) {
5608 	ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
5609 		   FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5610 		   FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5611       }
5612       /* For iso-view the city.wall graphics include the full city, whereas
5613        * for non-iso view they are an overlay on top of the base city
5614        * graphic. */
5615       if (t->type == TS_OVERHEAD || pcity->client.walls <= 0) {
5616 	ADD_SPRITE(get_city_sprite(t->sprites.city.tile, pcity), TRUE,
5617                    FULL_TILE_X_OFFSET + t->city_offset_x,
5618                    FULL_TILE_Y_OFFSET + t->city_offset_y);
5619       }
5620       if (t->type == TS_ISOMETRIC && pcity->client.walls > 0) {
5621         struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5622         struct sprite *spr = NULL;
5623 
5624         if (cspr != NULL) {
5625           spr = get_city_sprite(cspr, pcity);
5626         }
5627         if (spr == NULL) {
5628           cspr = t->sprites.city.single_wall;
5629           if (cspr != NULL) {
5630             spr = get_city_sprite(cspr, pcity);
5631           }
5632         }
5633 
5634         if (spr != NULL) {
5635           ADD_SPRITE(spr, TRUE,
5636                      FULL_TILE_X_OFFSET + t->city_offset_x,
5637                      FULL_TILE_Y_OFFSET + t->city_offset_y);
5638         }
5639       }
5640       if (!gui_options.draw_full_citybar && pcity->client.occupied) {
5641 	ADD_SPRITE(get_city_sprite(t->sprites.city.occupied, pcity), TRUE,
5642                    FULL_TILE_X_OFFSET + t->occupied_offset_x,
5643                    FULL_TILE_Y_OFFSET + t->occupied_offset_y);
5644       }
5645       if (t->type == TS_OVERHEAD && pcity->client.walls > 0) {
5646         struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5647         struct sprite *spr = NULL;
5648 
5649         if (cspr != NULL) {
5650           spr = get_city_sprite(cspr, pcity);
5651         }
5652         if (spr == NULL) {
5653           cspr = t->sprites.city.single_wall;
5654           if (cspr != NULL) {
5655             spr = get_city_sprite(cspr, pcity);
5656           }
5657         }
5658 
5659         if (spr != NULL) {
5660           ADD_SPRITE_FULL(spr);
5661         }
5662       }
5663       if (pcity->client.unhappy) {
5664 	ADD_SPRITE_FULL(t->sprites.city.disorder);
5665       }
5666     }
5667     break;
5668 
5669   case LAYER_SPECIAL2:
5670     if (NULL != pterrain) {
5671       if (ptile) {
5672         extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5673           if (tile_has_extra(ptile, pextra)
5674               && is_extra_drawing_enabled(pextra)
5675               && t->sprites.extras[extra_index(pextra)].u.bmf.middleground) {
5676             bool hidden = FALSE;
5677 
5678             extra_type_list_iterate(pextra->hiders, phider) {
5679               if (BV_ISSET(textras, extra_index(phider))) {
5680                 hidden = TRUE;
5681                 break;
5682               }
5683             } extra_type_list_iterate_end;
5684 
5685             if (!hidden) {
5686               ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.middleground);
5687             }
5688           }
5689         } extra_type_list_iterate_end;
5690       }
5691 
5692       extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE2], pextra) {
5693         if (BV_ISSET(textras, extra_index(pextra))
5694             && is_extra_drawing_enabled(pextra)) {
5695           bool hidden = FALSE;
5696 
5697           extra_type_list_iterate(pextra->hiders, phider) {
5698             if (BV_ISSET(textras, extra_index(phider))) {
5699               hidden = TRUE;
5700               break;
5701             }
5702           } extra_type_list_iterate_end;
5703 
5704           if (!hidden) {
5705             ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5706           }
5707         }
5708       } extra_type_list_iterate_end;
5709     }
5710     break;
5711 
5712   case LAYER_UNIT:
5713   case LAYER_FOCUS_UNIT:
5714     if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
5715       bool stacked = ptile && (unit_list_size(ptile->units) > 1);
5716       bool backdrop = !pcity;
5717 
5718       if (ptile && unit_is_in_focus(punit)
5719 	  && t->sprites.unit.select[0]) {
5720 	/* Special case for drawing the selection rectangle.  The blinking
5721 	 * unit is handled separately, inside get_drawable_unit(). */
5722 	ADD_SPRITE_SIMPLE(t->sprites.unit.select[focus_unit_state]);
5723       }
5724 
5725       sprs += fill_unit_sprite_array(t, sprs, punit, stacked, backdrop);
5726     } else if (putype != NULL && layer == LAYER_UNIT) {
5727       /* Only the sprite for the unit type. */
5728       sprs += fill_unit_type_sprite_array(t, sprs, putype,
5729                                           direction8_invalid());
5730     }
5731     break;
5732 
5733   case LAYER_SPECIAL3:
5734     if (NULL != pterrain) {
5735       if (ptile) {
5736         bool show_flag = FALSE;
5737         struct player *eowner = extra_owner(ptile);
5738 
5739         extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5740           if (is_extra_drawing_enabled(pextra)
5741               && tile_has_extra(ptile, pextra)
5742               && t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5743             bool hidden = FALSE;
5744 
5745             extra_type_list_iterate(pextra->hiders, phider) {
5746               if (BV_ISSET(textras, extra_index(phider))) {
5747                 hidden = TRUE;
5748                 break;
5749               }
5750             } extra_type_list_iterate_end;
5751 
5752             if (!hidden) {
5753               if (t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5754                 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.foreground);
5755               }
5756             }
5757           }
5758         } extra_type_list_iterate_end;
5759 
5760         /* Show base flag. Not part of previous iteration as
5761          * "extras of ESTYLE_3_LAYER" != "bases" */
5762         if (eowner != NULL) {
5763           extra_type_list_iterate(t->flagged_bases_list, pextra) {
5764             if (tile_has_extra(ptile, pextra)) {
5765               bool hidden = FALSE;
5766 
5767               extra_type_list_iterate(pextra->hiders, phider) {
5768                 if (BV_ISSET(textras, extra_index(phider))) {
5769                   hidden = TRUE;
5770                   break;
5771                 }
5772               } extra_type_list_iterate_end;
5773 
5774               if (!hidden) {
5775                 show_flag = TRUE;
5776               }
5777             }
5778           } extra_type_list_iterate_end;
5779 
5780           if (show_flag) {
5781             ADD_SPRITE(get_nation_flag_sprite(t, nation_of_player(eowner)), TRUE,
5782                        FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5783                        FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5784           }
5785         }
5786       }
5787     }
5788     break;
5789 
5790   case LAYER_FOG:
5791     sprs += fill_fog_sprite_array(t, sprs, ptile, pedge, pcorner);
5792     break;
5793 
5794   case LAYER_CITY2:
5795     /* City size.  Drawing this under fog makes it hard to read. */
5796     if (pcity && gui_options.draw_cities && !gui_options.draw_full_citybar) {
5797       bool warn = FALSE;
5798       unsigned int size = city_size_get(pcity);
5799 
5800       ADD_SPRITE(t->sprites.city.size[size % 10],
5801                  FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5802       if (10 <= size) {
5803         ADD_SPRITE(t->sprites.city.size_tens[(size / 10)
5804                    % 10], FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5805         if (100 <= size) {
5806           struct sprite *sprite =
5807               t->sprites.city.size_hundreds[(size / 100) % 10];
5808 
5809           if (NULL != sprite) {
5810             ADD_SPRITE(sprite, FALSE,
5811                        FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5812           } else {
5813             warn = TRUE;
5814           }
5815           if (1000 <= size) {
5816             warn = TRUE;
5817           }
5818         }
5819       }
5820 
5821       if (warn) {
5822         /* Warn only once by tileset. */
5823         static char last_reported[256] = "";
5824 
5825         if (0 != strcmp(last_reported, t->name)) {
5826           log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5827                        "such as %d. Size not displayed as expected."),
5828                      t->name, size);
5829           sz_strlcpy(last_reported, t->name);
5830         }
5831       }
5832     }
5833     break;
5834 
5835   case LAYER_GRID2:
5836     if (t->type == TS_OVERHEAD) {
5837       sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5838 				     punit, pcity, citymode);
5839     }
5840     break;
5841 
5842   case LAYER_OVERLAYS:
5843     sprs += fill_city_overlays_sprite_array(t, sprs, ptile, citymode);
5844     if (mapdeco_is_crosshair_set(ptile)) {
5845       ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5846     }
5847     break;
5848 
5849   case LAYER_CITYBAR:
5850   case LAYER_TILELABEL:
5851     /* Nothing.  This is just a placeholder. */
5852     break;
5853 
5854   case LAYER_GOTO:
5855     if (ptile && goto_is_active()) {
5856       sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
5857     }
5858     break;
5859 
5860   case LAYER_WORKERTASK:
5861     if (citymode != NULL && ptile != NULL) {
5862       worker_task_list_iterate(citymode->task_reqs, ptask) {
5863         if (ptask->ptile == ptile) {
5864           switch (ptask->act) {
5865           case ACTIVITY_MINE:
5866             if (ptask->tgt == NULL) {
5867               ADD_SPRITE(t->sprites.unit.plant,
5868                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5869                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5870             } else {
5871               ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5872                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5873                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5874             }
5875             break;
5876           case ACTIVITY_IRRIGATE:
5877             if (ptask->tgt == NULL) {
5878               ADD_SPRITE(t->sprites.unit.irrigate,
5879                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5880                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5881             } else {
5882               ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5883                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5884                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5885             }
5886             break;
5887           case ACTIVITY_GEN_ROAD:
5888             if (ptask->tgt != NULL) {
5889               ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5890                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5891                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5892             }
5893             break;
5894           case ACTIVITY_TRANSFORM:
5895             ADD_SPRITE(t->sprites.unit.transform,
5896                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5897                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5898             break;
5899           case ACTIVITY_POLLUTION:
5900           case ACTIVITY_FALLOUT:
5901             if (ptask->tgt != NULL) {
5902               ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].rmact,
5903                          TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5904                          FULL_TILE_Y_OFFSET + t->activity_offset_y);
5905             }
5906             break;
5907           default:
5908             break;
5909           }
5910         }
5911       } worker_task_list_iterate_end;
5912     }
5913     break;
5914 
5915   case LAYER_EDITOR:
5916     if (ptile && editor_is_active()) {
5917       if (editor_tile_is_selected(ptile)) {
5918         int color = 2 % tileset_num_city_colors(tileset);
5919         ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
5920       }
5921 
5922       if (NULL != map_startpos_get(ptile)) {
5923         /* FIXME: Use a more representative sprite. */
5924         ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5925       }
5926     }
5927     break;
5928 
5929   case LAYER_COUNT:
5930     fc_assert(FALSE);
5931     break;
5932   }
5933 
5934   return sprs - save_sprs;
5935 }
5936 
5937 /**********************************************************************
5938   Set city tiles sprite values; should only happen after
5939   tilespec_load_tiles().
5940 ***********************************************************************/
tileset_setup_city_tiles(struct tileset * t,int style)5941 void tileset_setup_city_tiles(struct tileset *t, int style)
5942 {
5943   if (style == game.control.styles_count - 1) {
5944     int i;
5945 
5946     /* Free old sprites */
5947     free_city_sprite(t->sprites.city.tile);
5948 
5949     for (i = 0; i < NUM_WALL_TYPES; i++) {
5950       free_city_sprite(t->sprites.city.wall[i]);
5951       t->sprites.city.wall[i] = NULL;
5952     }
5953     free_city_sprite(t->sprites.city.single_wall);
5954     t->sprites.city.single_wall = NULL;
5955 
5956     free_city_sprite(t->sprites.city.occupied);
5957 
5958     t->sprites.city.tile = load_city_sprite(t, "city");
5959 
5960     for (i = 0; i < NUM_WALL_TYPES; i++) {
5961       char buffer[256];
5962 
5963       fc_snprintf(buffer, sizeof(buffer), "bldg_%d", i);
5964       t->sprites.city.wall[i] = load_city_sprite(t, buffer);
5965     }
5966     t->sprites.city.single_wall = load_city_sprite(t, "wall");
5967 
5968     t->sprites.city.occupied = load_city_sprite(t, "occupied");
5969 
5970     for (style = 0; style < game.control.styles_count; style++) {
5971       if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
5972         tileset_error(LOG_FATAL, _("City style \"%s\": no city graphics."),
5973                       city_style_rule_name(style));
5974       }
5975       if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
5976         tileset_error(LOG_FATAL, _("City style \"%s\": no occupied graphics."),
5977                       city_style_rule_name(style));
5978       }
5979     }
5980   }
5981 }
5982 
5983 /****************************************************************************
5984   Return the amount of time between calls to toggle_focus_unit_state.
5985   The main loop needs to call toggle_focus_unit_state about this often
5986   to do the active-unit animation.
5987 ****************************************************************************/
get_focus_unit_toggle_timeout(const struct tileset * t)5988 double get_focus_unit_toggle_timeout(const struct tileset *t)
5989 {
5990   if (t->sprites.unit.select[0]) {
5991     return 0.1;
5992   } else {
5993     return 0.5;
5994   }
5995 }
5996 
5997 /****************************************************************************
5998   Reset the focus unit state.  This should be called when changing
5999   focus units.
6000 ****************************************************************************/
reset_focus_unit_state(struct tileset * t)6001 void reset_focus_unit_state(struct tileset *t)
6002 {
6003   focus_unit_state = 0;
6004 }
6005 
6006 /****************************************************************************
6007   Setup tileset for showing combat where focus unit participates.
6008 ****************************************************************************/
focus_unit_in_combat(struct tileset * t)6009 void focus_unit_in_combat(struct tileset *t)
6010 {
6011   if (!t->sprites.unit.select[0]) {
6012     reset_focus_unit_state(t);
6013   }
6014 }
6015 
6016 /****************************************************************************
6017   Toggle/increment the focus unit state.  This should be called once
6018   every get_focus_unit_toggle_timeout() seconds.
6019 ****************************************************************************/
toggle_focus_unit_state(struct tileset * t)6020 void toggle_focus_unit_state(struct tileset *t)
6021 {
6022   focus_unit_state++;
6023   if (t->sprites.unit.select[0]) {
6024     focus_unit_state %= NUM_TILES_SELECT;
6025   } else {
6026     focus_unit_state %= 2;
6027   }
6028 }
6029 
6030 /**********************************************************************
6031   Find unit that we can display from given tile.
6032 ***********************************************************************/
get_drawable_unit(const struct tileset * t,struct tile * ptile,const struct city * citymode)6033 struct unit *get_drawable_unit(const struct tileset *t,
6034 			       struct tile *ptile,
6035 			       const struct city *citymode)
6036 {
6037   struct unit *punit = find_visible_unit(ptile);
6038 
6039   if (punit == NULL) {
6040     return NULL;
6041   }
6042 
6043   if (citymode && unit_owner(punit) == city_owner(citymode)) {
6044     return NULL;
6045   }
6046 
6047   if (!unit_is_in_focus(punit)
6048       || t->sprites.unit.select[0] || focus_unit_state == 0) {
6049     return punit;
6050   } else {
6051     return NULL;
6052   }
6053 }
6054 
6055 /****************************************************************************
6056   This patch unloads all sprites from the sprite hash (the hash itself
6057   is left intact).
6058 ****************************************************************************/
unload_all_sprites(struct tileset * t)6059 static void unload_all_sprites(struct tileset *t)
6060 {
6061   if (t->sprite_hash) {
6062     sprite_hash_iterate(t->sprite_hash, tag_name, ss) {
6063       while (ss->ref_count > 0) {
6064         unload_sprite(t, tag_name);
6065       }
6066     } sprite_hash_iterate_end;
6067   }
6068 }
6069 
6070 /**********************************************************************
6071   Free all sprites from tileset.
6072 ***********************************************************************/
tileset_free_tiles(struct tileset * t)6073 void tileset_free_tiles(struct tileset *t)
6074 {
6075   int i;
6076 
6077   log_debug("tileset_free_tiles()");
6078 
6079   unload_all_sprites(t);
6080 
6081   free_city_sprite(t->sprites.city.tile);
6082   t->sprites.city.tile = NULL;
6083 
6084   for (i = 0; i < NUM_WALL_TYPES; i++) {
6085     free_city_sprite(t->sprites.city.wall[i]);
6086     t->sprites.city.wall[i] = NULL;
6087   }
6088   free_city_sprite(t->sprites.city.single_wall);
6089   t->sprites.city.single_wall = NULL;
6090 
6091   free_city_sprite(t->sprites.city.occupied);
6092   t->sprites.city.occupied = NULL;
6093 
6094   if (t->sprite_hash) {
6095     sprite_hash_destroy(t->sprite_hash);
6096     t->sprite_hash = NULL;
6097   }
6098 
6099   small_sprite_list_iterate(t->small_sprites, ss) {
6100     small_sprite_list_remove(t->small_sprites, ss);
6101     if (ss->file) {
6102       free(ss->file);
6103     }
6104     fc_assert(ss->sprite == NULL);
6105     free(ss);
6106   } small_sprite_list_iterate_end;
6107 
6108   specfile_list_iterate(t->specfiles, sf) {
6109     specfile_list_remove(t->specfiles, sf);
6110     free(sf->file_name);
6111     if (sf->big_sprite) {
6112       free_sprite(sf->big_sprite);
6113       sf->big_sprite = NULL;
6114     }
6115     free(sf);
6116   } specfile_list_iterate_end;
6117 
6118   sprite_vector_iterate(&t->sprites.city.worked_tile_overlay, psprite) {
6119     free_sprite(*psprite);
6120   } sprite_vector_iterate_end;
6121   sprite_vector_free(&t->sprites.city.worked_tile_overlay);
6122 
6123   sprite_vector_iterate(&t->sprites.city.unworked_tile_overlay, psprite) {
6124     free_sprite(*psprite);
6125   } sprite_vector_iterate_end;
6126   sprite_vector_free(&t->sprites.city.unworked_tile_overlay);
6127 
6128   if (t->sprites.tx.fullfog) {
6129     free(t->sprites.tx.fullfog);
6130     t->sprites.tx.fullfog = NULL;
6131   }
6132 
6133   sprite_vector_free(&t->sprites.colors.overlays);
6134   sprite_vector_free(&t->sprites.explode.unit);
6135   sprite_vector_free(&t->sprites.nation_flag);
6136   sprite_vector_free(&t->sprites.nation_shield);
6137   sprite_vector_free(&t->sprites.citybar.occupancy);
6138 
6139   tileset_background_free(t);
6140 }
6141 
6142 /**************************************************************************
6143   Return the sprite for drawing the given spaceship part.
6144 **************************************************************************/
get_spaceship_sprite(const struct tileset * t,enum spaceship_part part)6145 struct sprite *get_spaceship_sprite(const struct tileset *t,
6146 				    enum spaceship_part part)
6147 {
6148   return t->sprites.spaceship[part];
6149 }
6150 
6151 /**************************************************************************
6152   Return a sprite for the given citizen.  The citizen's type is given,
6153   as well as their index (in the range [0..city_size_get(pcity))).  The
6154   citizen's city can be used to determine which sprite to use (a NULL
6155   value indicates there is no city; i.e., the sprite is just being
6156   used as a picture).
6157 **************************************************************************/
get_citizen_sprite(const struct tileset * t,enum citizen_category type,int citizen_index,const struct city * pcity)6158 struct sprite *get_citizen_sprite(const struct tileset *t,
6159 				  enum citizen_category type,
6160 				  int citizen_index,
6161 				  const struct city *pcity)
6162 {
6163   const struct citizen_graphic *graphic;
6164   int gfx_index = citizen_index;
6165 
6166   if (pcity != NULL) {
6167     gfx_index += pcity->client.first_citizen_index;
6168   }
6169 
6170   if (type < CITIZEN_SPECIALIST) {
6171     fc_assert(type >= 0);
6172     graphic = &t->sprites.citizen[type];
6173   } else {
6174     fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
6175     graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
6176   }
6177 
6178   if (graphic->count == 0) {
6179     return NULL;
6180   }
6181 
6182   return graphic->sprite[gfx_index % graphic->count];
6183 }
6184 
6185 /**************************************************************************
6186   Return the sprite for the nation.
6187 **************************************************************************/
get_nation_flag_sprite(const struct tileset * t,const struct nation_type * pnation)6188 struct sprite *get_nation_flag_sprite(const struct tileset *t,
6189 				      const struct nation_type *pnation)
6190 {
6191   return t->sprites.nation_flag.p[nation_index(pnation)];
6192 }
6193 
6194 /**************************************************************************
6195   Return the shield sprite for the nation.
6196 **************************************************************************/
get_nation_shield_sprite(const struct tileset * t,const struct nation_type * pnation)6197 struct sprite *get_nation_shield_sprite(const struct tileset *t,
6198                                         const struct nation_type *pnation)
6199 {
6200   return t->sprites.nation_shield.p[nation_index(pnation)];
6201 }
6202 
6203 /**************************************************************************
6204   Return the sprite for the technology/advance.
6205 **************************************************************************/
get_tech_sprite(const struct tileset * t,Tech_type_id tech)6206 struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
6207 {
6208   fc_assert_ret_val(0 <= tech && tech < advance_count(), NULL);
6209   return t->sprites.tech[tech];
6210 }
6211 
6212 /**************************************************************************
6213   Return the sprite for the building/improvement.
6214 **************************************************************************/
get_building_sprite(const struct tileset * t,struct impr_type * pimprove)6215 struct sprite *get_building_sprite(const struct tileset *t,
6216                                    struct impr_type *pimprove)
6217 {
6218   fc_assert_ret_val(NULL != pimprove, NULL);
6219   return t->sprites.building[improvement_index(pimprove)];
6220 }
6221 
6222 /****************************************************************************
6223   Return the sprite for the government.
6224 ****************************************************************************/
get_government_sprite(const struct tileset * t,const struct government * gov)6225 struct sprite *get_government_sprite(const struct tileset *t,
6226                                      const struct government *gov)
6227 {
6228   fc_assert_ret_val(NULL != gov, NULL);
6229   return t->sprites.government[government_index(gov)];
6230 }
6231 
6232 /****************************************************************************
6233   Return the sprite for the unit type (the base "unit" sprite).
6234 ****************************************************************************/
get_unittype_sprite(const struct tileset * t,const struct unit_type * punittype,enum direction8 facing,bool icon)6235 struct sprite *get_unittype_sprite(const struct tileset *t,
6236                                    const struct unit_type *punittype,
6237                                    enum direction8 facing,
6238                                    bool icon)
6239 {
6240   int uidx = utype_index(punittype);
6241 
6242   fc_assert_ret_val(NULL != punittype, NULL);
6243 
6244   if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
6245     /* Fallback to random orientation sprite.
6246      * The randomness was fixed at tileset load time for stability
6247      * (in tileset_setup_unit_type_from_tag()); here we need to adapt
6248      * that to the map topology (which is now known).
6249      * default_dir_seed was set to give uniform distribution for either
6250      * 6 or 8 valid directions.
6251      * Thus this direction is stable for a given unit type unless the
6252      * map topology changes. */
6253     unsigned int dir_index;
6254 
6255     fc_assert_ret_val(game.map.num_valid_dirs > 0, NULL);
6256     dir_index
6257       = t->sprites.units.default_dir_seed[uidx] % game.map.num_valid_dirs;
6258     facing = game.map.valid_dirs[dir_index];
6259     fc_assert_ret_val(is_valid_dir(facing), NULL);
6260   }
6261 
6262   if (t->sprites.units.icon[uidx]
6263       && (icon || t->sprites.units.facing[uidx][facing] == NULL)) {
6264     /* Has icon sprite */
6265     return t->sprites.units.icon[uidx];
6266   } else {
6267     return t->sprites.units.facing[uidx][facing];
6268   }
6269 }
6270 
6271 /**************************************************************************
6272   Return a "sample" sprite for this city style.
6273 **************************************************************************/
get_sample_city_sprite(const struct tileset * t,int style_idx)6274 struct sprite *get_sample_city_sprite(const struct tileset *t,
6275                                       int style_idx)
6276 {
6277   int num_thresholds =
6278     t->sprites.city.tile->styles[style_idx].land_num_thresholds;
6279 
6280   if (num_thresholds == 0) {
6281     return NULL;
6282   } else {
6283     return (t->sprites.city.tile->styles[style_idx]
6284             .land_thresholds[num_thresholds - 1].sprite);
6285   }
6286 }
6287 
6288 /**************************************************************************
6289   Return a sprite with an "arrow" theme graphic.
6290 **************************************************************************/
get_arrow_sprite(const struct tileset * t,enum arrow_type arrow)6291 struct sprite *get_arrow_sprite(const struct tileset *t,
6292                                 enum arrow_type arrow)
6293 {
6294   fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, NULL);
6295 
6296   return t->sprites.arrow[arrow];
6297 }
6298 
6299 /**************************************************************************
6300   Return a tax sprite for the given output type (usually gold/lux/sci).
6301 **************************************************************************/
get_tax_sprite(const struct tileset * t,Output_type_id otype)6302 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype)
6303 {
6304   switch (otype) {
6305   case O_SCIENCE:
6306     return t->sprites.tax_science;
6307   case O_GOLD:
6308     return t->sprites.tax_gold;
6309   case O_LUXURY:
6310     return t->sprites.tax_luxury;
6311   case O_TRADE:
6312   case O_FOOD:
6313   case O_SHIELD:
6314   case O_LAST:
6315     break;
6316   }
6317   return NULL;
6318 }
6319 
6320 /**************************************************************************
6321   Return event icon sprite
6322 **************************************************************************/
get_event_sprite(const struct tileset * t,enum event_type event)6323 struct sprite *get_event_sprite(const struct tileset *t, enum event_type event)
6324 {
6325   return t->sprites.events[event];
6326 }
6327 
6328 /**************************************************************************
6329   Return a thumbs-up/thumbs-down sprite to show treaty approval or
6330   disapproval.
6331 **************************************************************************/
get_treaty_thumb_sprite(const struct tileset * t,bool on_off)6332 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
6333 {
6334   return t->sprites.treaty_thumb[on_off ? 1 : 0];
6335 }
6336 
6337 /**************************************************************************
6338   Return a sprite_vector containing the animation sprites for a unit
6339   explosion.
6340 **************************************************************************/
get_unit_explode_animation(const struct tileset * t)6341 const struct sprite_vector *get_unit_explode_animation(const struct
6342 						       tileset *t)
6343 {
6344   return &t->sprites.explode.unit;
6345 }
6346 
6347 /****************************************************************************
6348   Return a sprite contining the single nuke graphic.
6349 
6350   TODO: This should be an animation like the unit explode animation.
6351 ****************************************************************************/
get_nuke_explode_sprite(const struct tileset * t)6352 struct sprite *get_nuke_explode_sprite(const struct tileset *t)
6353 {
6354   return t->sprites.explode.nuke;
6355 }
6356 
6357 /**************************************************************************
6358   Return all the sprites used for city bar drawing.
6359 **************************************************************************/
get_citybar_sprites(const struct tileset * t)6360 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
6361 {
6362   if (gui_options.draw_full_citybar) {
6363     return &t->sprites.citybar;
6364   } else {
6365     return NULL;
6366   }
6367 }
6368 
6369 /**************************************************************************
6370   Return all the sprites used for editor icons, images, etc.
6371 **************************************************************************/
get_editor_sprites(const struct tileset * t)6372 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
6373 {
6374   return &t->sprites.editor;
6375 }
6376 
6377 /**************************************************************************
6378   Returns a sprite for the given cursor.  The "hot" coordinates (the
6379   active coordinates of the mouse relative to the sprite) are placed int
6380   (*hot_x, *hot_y).
6381   A cursor can consist of several frames to be used for animation.
6382 **************************************************************************/
get_cursor_sprite(const struct tileset * t,enum cursor_type cursor,int * hot_x,int * hot_y,int frame)6383 struct sprite *get_cursor_sprite(const struct tileset *t,
6384 				 enum cursor_type cursor,
6385 				 int *hot_x, int *hot_y, int frame)
6386 {
6387   *hot_x = t->sprites.cursor[cursor].hot_x;
6388   *hot_y = t->sprites.cursor[cursor].hot_y;
6389   return t->sprites.cursor[cursor].frame[frame];
6390 }
6391 
6392 /****************************************************************************
6393   Return a sprite for the given icon.  Icons are used by the operating
6394   system/window manager.  Usually freeciv has to tell the OS what icon to
6395   use.
6396 
6397   Note that this function will return NULL before the sprites are loaded.
6398   The GUI code must be sure to call tileset_load_tiles before setting the
6399   top-level icon.
6400 ****************************************************************************/
get_icon_sprite(const struct tileset * t,enum icon_type icon)6401 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
6402 {
6403   return t->sprites.icon[icon];
6404 }
6405 
6406 /****************************************************************************
6407   Returns a sprite with the "user-attention" crosshair graphic.
6408 
6409   FIXME: This function shouldn't be needed if the attention graphics are
6410   drawn natively by the tileset code.
6411 ****************************************************************************/
get_attention_crosshair_sprite(const struct tileset * t)6412 struct sprite *get_attention_crosshair_sprite(const struct tileset *t)
6413 {
6414   return t->sprites.user.attention;
6415 }
6416 
6417 /****************************************************************************
6418   Returns a sprite for the given indicator with the given index.  The
6419   index should be in [0, NUM_TILES_PROGRESS).
6420 ****************************************************************************/
get_indicator_sprite(const struct tileset * t,enum indicator_type indicator,int idx)6421 struct sprite *get_indicator_sprite(const struct tileset *t,
6422                                     enum indicator_type indicator,
6423                                     int idx)
6424 {
6425   idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
6426 
6427   fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, NULL);
6428 
6429   return t->sprites.indicator[indicator][idx];
6430 }
6431 
6432 /****************************************************************************
6433   Return a sprite for the unhappiness of the unit - to be shown as an
6434   overlay on the unit in the city support dialog, for instance.
6435 
6436   May return NULL if there's no unhappiness.
6437 ****************************************************************************/
get_unit_unhappy_sprite(const struct tileset * t,const struct unit * punit,int happy_cost)6438 struct sprite *get_unit_unhappy_sprite(const struct tileset *t,
6439                                        const struct unit *punit,
6440                                        int happy_cost)
6441 {
6442   const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
6443 
6444   if (unhappy > 0) {
6445     return t->sprites.upkeep.unhappy[unhappy - 1];
6446   } else {
6447     return NULL;
6448   }
6449 }
6450 
6451 /****************************************************************************
6452   Return a sprite for the upkeep of the unit - to be shown as an overlay
6453   on the unit in the city support dialog, for instance.
6454 
6455   May return NULL if there's no upkeep of the kind.
6456 ****************************************************************************/
get_unit_upkeep_sprite(const struct tileset * t,Output_type_id otype,const struct unit * punit,const int * upkeep_cost)6457 struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
6458                                       Output_type_id otype,
6459                                       const struct unit *punit,
6460                                       const int *upkeep_cost)
6461 {
6462   const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES + 1);
6463 
6464   if (upkeep > 0) {
6465     return t->sprites.upkeep.output[otype][upkeep - 1];
6466   } else {
6467     return NULL;
6468   }
6469 }
6470 
6471 /****************************************************************************
6472   Return a rectangular sprite containing a fog "color".  This can be used
6473   for drawing fog onto arbitrary areas (like the overview).
6474 ****************************************************************************/
get_basic_fog_sprite(const struct tileset * t)6475 struct sprite *get_basic_fog_sprite(const struct tileset *t)
6476 {
6477   return t->sprites.tx.fog;
6478 }
6479 
6480 /****************************************************************************
6481   Return the tileset's color system.
6482 ****************************************************************************/
get_color_system(const struct tileset * t)6483 struct color_system *get_color_system(const struct tileset *t)
6484 {
6485   return t->color_system;
6486 }
6487 
6488 /****************************************************************************
6489   Loads preferred theme if there's any.
6490 ****************************************************************************/
tileset_use_preferred_theme(const struct tileset * t)6491 void tileset_use_preferred_theme(const struct tileset *t)
6492 {
6493   char *default_theme_name = NULL;
6494   size_t default_theme_name_sz = 0;
6495   int i;
6496 
6497   switch (get_gui_type()) {
6498   case GUI_GTK2:
6499     default_theme_name = gui_options.gui_gtk2_default_theme_name;
6500     default_theme_name_sz = sizeof(gui_options.gui_gtk2_default_theme_name);
6501     break;
6502   case GUI_GTK3:
6503     default_theme_name = gui_options.gui_gtk3_default_theme_name;
6504     default_theme_name_sz = sizeof(gui_options.gui_gtk3_default_theme_name);
6505     break;
6506   case GUI_GTK3_22:
6507     default_theme_name = gui_options.gui_gtk3_22_default_theme_name;
6508     default_theme_name_sz = sizeof(gui_options.gui_gtk3_22_default_theme_name);
6509     break;
6510   case GUI_SDL:
6511     default_theme_name = gui_options.gui_sdl_default_theme_name;
6512     default_theme_name_sz = sizeof(gui_options.gui_sdl_default_theme_name);
6513     break;
6514   case GUI_SDL2:
6515     default_theme_name = gui_options.gui_sdl2_default_theme_name;
6516     default_theme_name_sz = sizeof(gui_options.gui_sdl2_default_theme_name);
6517     break;
6518   case GUI_STUB:
6519   case GUI_XAW:
6520   case GUI_QT:
6521   case GUI_WEB:
6522     break;
6523   }
6524 
6525   if (NULL == default_theme_name || 0 == default_theme_name_sz) {
6526     /* Theme is not supported by this client. */
6527     return;
6528   }
6529 
6530   for (i = 0; i < t->num_preferred_themes; i++) {
6531     if (strcmp(t->preferred_themes[i], default_theme_name)) {
6532       if (popup_theme_suggestion_dialog(t->preferred_themes[i])) {
6533         log_debug("trying theme \"%s\".", t->preferred_themes[i]);
6534         if (load_theme(t->preferred_themes[i])) {
6535           (void) fc_strlcpy(default_theme_name, t->preferred_themes[i],
6536                             default_theme_name_sz);
6537           return;
6538         }
6539       }
6540     }
6541   }
6542   log_verbose("The tileset doesn't specify preferred themes or none of its "
6543               "preferred themes can be used. Using system default.");
6544   gui_clear_theme();
6545 }
6546 
6547 /****************************************************************************
6548   Initialize tileset structure
6549 ****************************************************************************/
tileset_init(struct tileset * t)6550 void tileset_init(struct tileset *t)
6551 {
6552   int wi;
6553 
6554   /* We currently have no city sprites loaded. */
6555   t->sprites.city.tile     = NULL;
6556 
6557   for (wi = 0; wi < NUM_WALL_TYPES; wi++) {
6558     t->sprites.city.wall[wi] = NULL;
6559   }
6560   t->sprites.city.single_wall = NULL;
6561 
6562   t->sprites.city.occupied = NULL;
6563 
6564   t->sprites.background.color = NULL;
6565   t->sprites.background.graphic = NULL;
6566 
6567   player_slots_iterate(pslot) {
6568     int edge, j, id = player_slot_index(pslot);
6569 
6570     for (edge = 0; edge < EDGE_COUNT; edge++) {
6571       for (j = 0; j < 2; j++) {
6572         t->sprites.player[id].grid_borders[edge][j] = NULL;
6573       }
6574     }
6575 
6576     t->sprites.player[id].color = NULL;
6577     t->sprites.player[id].background = NULL;
6578   } player_slots_iterate_end;
6579 
6580   t->max_upkeep_height = 0;
6581 }
6582 
6583 /****************************************************************************
6584   Fill the sprite array with sprites that together make a representative
6585   image of the given terrain type. Suitable for use as an icon and in list
6586   views.
6587 
6588   NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
6589   Using other values for 'layer' here will result in undefined behaviour. ;)
6590 ****************************************************************************/
fill_basic_terrain_layer_sprite_array(struct tileset * t,struct drawn_sprite * sprs,int layer,struct terrain * pterrain)6591 int fill_basic_terrain_layer_sprite_array(struct tileset *t,
6592                                           struct drawn_sprite *sprs,
6593                                           int layer,
6594                                           struct terrain *pterrain)
6595 {
6596   struct drawn_sprite *save_sprs = sprs;
6597   struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
6598 
6599   struct terrain *tterrain_near[8];
6600   bv_special tspecial_near[8];
6601 
6602   struct tile dummy_tile; /* :( */
6603 
6604   int i;
6605 
6606 
6607   memset(&dummy_tile, 0, sizeof(struct tile));
6608 
6609   for (i = 0; i < 8; i++) {
6610     tterrain_near[i] = pterrain;
6611     BV_CLR_ALL(tspecial_near[i]);
6612   }
6613 
6614   i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
6615   sprs += fill_terrain_sprite_array(t, sprs, i, &dummy_tile,
6616                                     pterrain, tterrain_near, draw);
6617 
6618   return sprs - save_sprs;
6619 }
6620 
6621 /****************************************************************************
6622   Return the sprite for the given resource type.
6623 ****************************************************************************/
get_resource_sprite(const struct tileset * t,const struct resource * presource)6624 struct sprite *get_resource_sprite(const struct tileset *t,
6625                                    const struct resource *presource)
6626 {
6627   if (presource == NULL) {
6628     return NULL;
6629   }
6630 
6631   return t->sprites.resource[resource_index(presource)];
6632 }
6633 
6634 /****************************************************************************
6635   Return a representative sprite for the given extra type.
6636 ****************************************************************************/
fill_basic_extra_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6637 int fill_basic_extra_sprite_array(const struct tileset *t,
6638                                   struct drawn_sprite *sprs,
6639                                   const struct extra_type *pextra)
6640 {
6641   int idx = extra_index(pextra);
6642   struct drawn_sprite *saved_sprs = sprs;
6643 
6644   switch (t->sprites.extras[idx].extrastyle) {
6645   case ESTYLE_SINGLE1:
6646   case ESTYLE_SINGLE2:
6647     ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.single);
6648     break;
6649   case ESTYLE_CARDINALS:
6650     ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.cardinals[0]);
6651     break;
6652   case ESTYLE_ROAD_ALL_SEPARATE:
6653   case ESTYLE_ROAD_PARITY_COMBINED:
6654   case ESTYLE_ROAD_ALL_COMBINED:
6655   case ESTYLE_RIVER:
6656     return fill_basic_road_sprite_array(t, sprs, pextra);
6657   case ESTYLE_3LAYER:
6658     return fill_basic_base_sprite_array(t, sprs, pextra);
6659   case ESTYLE_COUNT:
6660     fc_assert(t->sprites.extras[idx].extrastyle != ESTYLE_COUNT);
6661     break;
6662   }
6663 
6664   return sprs - saved_sprs;
6665 }
6666 
6667 /****************************************************************************
6668   Fills the sprite array with sprites that together make a representative
6669   image of the given road type. The image is suitable for use as an icon
6670   for the road type, for example.
6671 ****************************************************************************/
fill_basic_road_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6672 int fill_basic_road_sprite_array(const struct tileset *t,
6673                                  struct drawn_sprite *sprs,
6674                                  const struct extra_type *pextra)
6675 {
6676   struct drawn_sprite *saved_sprs = sprs;
6677   int idx;
6678   int i;
6679   enum extrastyle_id extrastyle;
6680 
6681   if (!t || !sprs || !pextra) {
6682     return 0;
6683   }
6684 
6685   idx = extra_index(pextra);
6686 
6687   if (!(0 <= idx && idx < game.control.num_extra_types)) {
6688     return 0;
6689   }
6690 
6691   extrastyle = t->sprites.extras[idx].extrastyle;
6692 
6693   if (extrastyle == ESTYLE_RIVER) {
6694     ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[0]);
6695   } else {
6696     for (i = 0; i < t->num_valid_tileset_dirs; i++) {
6697       if (!t->valid_tileset_dirs[i]) {
6698         continue;
6699       }
6700       if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
6701         ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.dir[i]);
6702       } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
6703         if ((i % 2) == 0) {
6704           ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.combo.even[1 << (i / 2)]);
6705         }
6706       } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
6707         ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.total[1 << i]);
6708       }
6709     }
6710   }
6711 
6712   return sprs - saved_sprs;
6713 }
6714 
6715 /****************************************************************************
6716   Fills the sprite array with sprites that together make a representative
6717   image of the given base type. The image is suitable for use as an icon
6718   for the base type, for example.
6719 ****************************************************************************/
fill_basic_base_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6720 int fill_basic_base_sprite_array(const struct tileset *t,
6721                                  struct drawn_sprite *sprs,
6722                                  const struct extra_type *pextra)
6723 {
6724   struct drawn_sprite *saved_sprs = sprs;
6725   int idx;
6726 
6727   if (!t || !sprs || !pextra) {
6728     return 0;
6729   }
6730 
6731   idx = extra_index(pextra);
6732 
6733   if (!(0 <= idx && idx < game.control.num_extra_types)) {
6734     return 0;
6735   }
6736 
6737 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
6738   if ((x) != NULL) {\
6739     ADD_SPRITE_FULL(x);\
6740   }\
6741 } while (0)
6742 
6743   /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
6744   ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.background);
6745   ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.middleground);
6746   ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.foreground);
6747 
6748 #undef ADD_SPRITE_IF_NOT_NULL
6749 
6750   return sprs - saved_sprs;
6751 }
6752 
6753 /****************************************************************************
6754   Setup tiles for one player using the player color.
6755 ****************************************************************************/
tileset_player_init(struct tileset * t,struct player * pplayer)6756 void tileset_player_init(struct tileset *t, struct player *pplayer)
6757 {
6758   int plrid, i, j;
6759   struct sprite *color;
6760 
6761   fc_assert_ret(pplayer != NULL);
6762 
6763   plrid = player_index(pplayer);
6764   fc_assert_ret(plrid >= 0);
6765   fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6766 
6767   /* Free all data before recreating it. */
6768   tileset_player_free(t, plrid);
6769 
6770   if (player_has_color(t, pplayer)) {
6771     t->sprites.player[plrid].color = color
6772       = create_plr_sprite(get_player_color(t, pplayer));
6773   } else {
6774     /* XXX: if player hasn't been assigned a color, perhaps there's no
6775      * point proceeding with an arbitrary color; this should only happen
6776      * in pregame. Probably blank sprites would be better. */
6777 
6778     fc_assert_ret(t->sprites.background.color != NULL);
6779 
6780     color = t->sprites.background.color;
6781   }
6782 
6783   t->sprites.player[plrid].background
6784     = crop_sprite(color, 0, 0,
6785                   t->normal_tile_width, t->normal_tile_height,
6786                   t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6787 
6788   for (i = 0; i < EDGE_COUNT; i++) {
6789     for (j = 0; j < 2; j++) {
6790       struct sprite *s;
6791 
6792       if (color && t->sprites.grid.borders[i][j]) {
6793         s = crop_sprite(color, 0, 0,
6794                         t->normal_tile_width, t->normal_tile_height,
6795                         t->sprites.grid.borders[i][j], 0, 0, 1.0f, FALSE);
6796       } else {
6797         s = t->sprites.grid.borders[i][j];
6798       }
6799       t->sprites.player[plrid].grid_borders[i][j] = s;
6800     }
6801   }
6802 }
6803 
6804 /****************************************************************************
6805   Free tiles for one player using the player color.
6806 ****************************************************************************/
tileset_player_free(struct tileset * t,int plrid)6807 static void tileset_player_free(struct tileset *t, int plrid)
6808 {
6809   int i, j;
6810 
6811   fc_assert_ret(plrid >= 0);
6812   fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6813 
6814   if (t->sprites.player[plrid].color) {
6815     free_sprite(t->sprites.player[plrid].color);
6816     t->sprites.player[plrid].color = NULL;
6817   }
6818   if (t->sprites.player[plrid].background) {
6819     free_sprite(t->sprites.player[plrid].background);
6820     t->sprites.player[plrid].background = NULL;
6821   }
6822 
6823   for (i = 0; i < EDGE_COUNT; i++) {
6824     for (j = 0; j < 2; j++) {
6825       if (t->sprites.player[plrid].grid_borders[i][j]) {
6826         free_sprite(t->sprites.player[plrid].grid_borders[i][j]);
6827         t->sprites.player[plrid].grid_borders[i][j] = NULL;
6828       }
6829     }
6830   }
6831 }
6832 
6833 /****************************************************************************
6834   Setup tiles for the background.
6835 ****************************************************************************/
tileset_background_init(struct tileset * t)6836 void tileset_background_init(struct tileset *t)
6837 {
6838   /* Free all data before recreating it. */
6839   tileset_background_free(t);
6840 
6841   /* generate background color */
6842   t->sprites.background.color
6843     = create_plr_sprite(ensure_color(game.plr_bg_color));
6844 
6845   /* Chop up and build the background graphics. */
6846   t->sprites.background.graphic
6847     = crop_sprite(t->sprites.background.color, 0, 0,
6848                   t->normal_tile_width, t->normal_tile_height,
6849                   t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6850 }
6851 
6852 /****************************************************************************
6853   Free tiles for the background.
6854 ****************************************************************************/
tileset_background_free(struct tileset * t)6855 void tileset_background_free(struct tileset *t)
6856 {
6857   if (t->sprites.background.color) {
6858     free_sprite(t->sprites.background.color);
6859     t->sprites.background.color = NULL;
6860   }
6861 
6862   if (t->sprites.background.graphic) {
6863     free_sprite(t->sprites.background.graphic);
6864     t->sprites.background.graphic = NULL;
6865   }
6866 }
6867 
6868 /****************************************************************************
6869   Reset tileset data specific to ruleset.
6870 ****************************************************************************/
tileset_ruleset_reset(struct tileset * t)6871 void tileset_ruleset_reset(struct tileset *t)
6872 {
6873   int i;
6874 
6875   for (i = 0; i < ESTYLE_COUNT; i++) {
6876     if (t->style_lists[i] != NULL) {
6877       extra_type_list_destroy(t->style_lists[i]);
6878       t->style_lists[i] = extra_type_list_new();
6879     }
6880   }
6881 
6882   if (t->flagged_bases_list != NULL) {
6883     extra_type_list_destroy(t->flagged_bases_list);
6884     t->flagged_bases_list = extra_type_list_new();
6885   }
6886 }
6887 
6888 /****************************************************************************
6889   Is tileset in sane state?
6890 ****************************************************************************/
tileset_is_fully_loaded(void)6891 bool tileset_is_fully_loaded(void)
6892 {
6893   return !tileset_update;
6894 }
6895 
6896 /****************************************************************************
6897   Return tileset name
6898 ****************************************************************************/
tileset_name_get(struct tileset * t)6899 const char *tileset_name_get(struct tileset *t)
6900 {
6901   return t->given_name;
6902 }
6903 
6904 /****************************************************************************
6905   Return tileset version
6906 ****************************************************************************/
tileset_version(struct tileset * t)6907 const char *tileset_version(struct tileset *t)
6908 {
6909   return t->version;
6910 }
6911 
6912 /****************************************************************************
6913   Return tileset description summary
6914 ****************************************************************************/
tileset_summary(struct tileset * t)6915 const char *tileset_summary(struct tileset *t)
6916 {
6917   return t->summary;
6918 }
6919 
6920 /****************************************************************************
6921   Return tileset description body
6922 ****************************************************************************/
tileset_description(struct tileset * t)6923 const char *tileset_description(struct tileset *t)
6924 {
6925   return t->description;
6926 }
6927 
6928 /****************************************************************************
6929   Return tileset topology index
6930 ****************************************************************************/
tileset_topo_index(struct tileset * t)6931 int tileset_topo_index(struct tileset *t)
6932 {
6933   return t->ts_topo_idx;
6934 }
6935