Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / client / tilespec.c
blob367a54ad98c49f546b369c731579381d312a0ccf
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.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /***********************************************************************
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 ***********************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include <fc_config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h> /* exit */
26 #include <stdarg.h>
27 #include <string.h>
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"
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"
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"
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"
77 #include "tilespec.h"
79 #define TILESPEC_CAPSTR "+Freeciv-2.6-tilespec duplicates_ok"
81 * Tilespec capabilities acceptable to this program:
83 * +Freeciv-2.4-tilespec
84 * - basic format for Freeciv versions 2.4.x; required
86 * +Freeciv-tilespec-Devel-YYYY.MMM.DD
87 * - tilespec of the development version at the given data
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")
95 #define SPEC_CAPSTR "+Freeciv-2.6-spec"
97 * Individual spec file capabilities acceptable to this program:
99 * +Freeciv-2.3-spec
100 * - basic format for Freeciv versions 2.3.x; required
103 #define TILESPEC_SUFFIX ".tilespec"
104 #define TILE_SECTION_PREFIX "tile_"
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
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
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"
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
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"};
144 static const int DIR4_TO_DIR8[4] =
145 { DIR8_NORTH, DIR8_SOUTH, DIR8_EAST, DIR8_WEST };
147 enum match_style {
148 MATCH_NONE,
149 MATCH_SAME, /* "boolean" match */
150 MATCH_PAIR,
151 MATCH_FULL
154 enum sprite_type {
155 CELL_WHOLE, /* entire tile */
156 CELL_CORNER /* corner of tile */
159 struct drawing_data {
160 bool init;
162 char *name;
164 int num_layers; /* 1 thru MAX_NUM_LAYERS. */
165 #define MAX_NUM_LAYERS 3
167 struct drawing_layer {
168 bool is_tall;
169 int offset_x, offset_y;
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 */
176 enum sprite_type sprite_type;
178 struct sprite_vector base;
179 struct sprite *match[MAX_INDEX_CARDINAL];
180 struct sprite **cells;
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];
187 bool is_reversed;
189 int blending; /* layer, 0 = none */
190 struct sprite *blender;
191 struct sprite *blend[4]; /* indexed by a direction4 */
194 struct city_style_threshold {
195 struct sprite *sprite;
198 struct city_sprite {
199 struct {
200 int land_num_thresholds;
201 struct city_style_threshold *land_thresholds;
202 } *styles;
203 int num_styles;
206 struct river_sprites {
207 struct sprite
208 *spec[MAX_INDEX_CARDINAL],
209 *outlet[MAX_INDEX_CARDINAL];
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 */
218 *icon[ICON_COUNT],
220 *events[E_COUNT],
222 /* The panel sprites for showing tax % allocations. */
223 *tax_luxury, *tax_science, *tax_gold,
224 *dither_tile; /* only used for isometric view */
226 struct {
227 struct sprite
228 *tile,
229 *worked_tile,
230 *unworked_tile;
231 } mask;
233 struct sprite *tech[A_LAST];
234 struct sprite *building[B_LAST];
235 struct sprite *government[G_LAST];
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;
243 struct sprite *resource[MAX_NUM_RESOURCES];
245 struct sprite_vector nation_flag;
246 struct sprite_vector nation_shield;
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];
389 struct drawing_data *drawing[MAX_NUM_ITEMS];
392 struct specfile {
393 struct sprite *big_sprite;
394 char *file_name;
397 #define SPECLIST_TAG specfile
398 #define SPECLIST_TYPE struct specfile
399 #include "speclist.h"
401 #define specfile_list_iterate(list, pitem) \
402 TYPED_LIST_ITERATE(struct specfile, list, pitem)
403 #define specfile_list_iterate_end LIST_ITERATE_END
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.
410 struct small_sprite {
411 int ref_count;
413 /* The sprite is in this file. */
414 char *file;
416 /* Or, the sprite is in this file at the location. */
417 struct specfile *sf;
418 int x, y, width, height;
420 /* A little more (optional) data. */
421 int hot_x, hot_y;
423 struct sprite *sprite;
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
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
444 /* 'struct drawing_hash' and related functions. */
445 static void drawing_data_destroy(struct drawing_data *draw);
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"
453 #define SPECHASH_TAG estyle
454 #define SPECHASH_ASTR_KEY_TYPE
455 #define SPECHASH_ENUM_DATA_TYPE extrastyle_id
456 #include "spechash.h"
458 struct tileset {
459 char name[512];
460 char given_name[MAX_LEN_NAME];
461 char version[MAX_LEN_NAME];
462 int priority;
464 char *summary;
465 char *description;
467 enum ts_type type;
468 int hex_width, hex_height;
469 int ts_topo_idx;
471 int normal_tile_width, normal_tile_height;
472 int full_tile_width, full_tile_height;
473 int unit_tile_width, unit_tile_height;
474 int small_sprite_width, small_sprite_height;
476 int max_upkeep_height;
478 char *main_intro_filename;
479 char *minimap_intro_filename;
481 int city_names_font_size, city_productions_font_size;
483 enum fog_style fogstyle;
484 enum darkness_style darkness_style;
485 int darkness_layer;
487 int unit_flag_offset_x, unit_flag_offset_y;
488 int city_flag_offset_x, city_flag_offset_y;
489 int unit_offset_x, unit_offset_y;
490 int city_offset_x, city_offset_y;
492 int citybar_offset_y;
493 int tilelabel_offset_y;
494 int activity_offset_x;
495 int activity_offset_y;
496 int occupied_offset_x;
497 int occupied_offset_y;
498 int unit_upkeep_offset_y;
499 int unit_upkeep_small_offset_y;
501 #define NUM_CORNER_DIRS 4
502 #define TILES_PER_CORNER 4
503 int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
504 int num_index_valid, num_index_cardinal;
505 enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
507 struct tileset_layer {
508 char **match_types;
509 size_t match_count;
510 } layers[MAX_NUM_LAYERS];
512 struct specfile_list *specfiles;
513 struct small_sprite_list *small_sprites;
515 /* This hash table maps tilespec tags to struct small_sprites. */
516 struct sprite_hash *sprite_hash;
518 /* This hash table maps terrain graphic strings to drawing data. */
519 struct drawing_hash *tile_hash;
521 struct estyle_hash *estyle_hash;
523 struct named_sprites sprites;
525 struct color_system *color_system;
527 struct extra_type_list *style_lists[ESTYLE_COUNT];
529 struct extra_type_list *flagged_bases_list;
531 int num_preferred_themes;
532 char** preferred_themes;
535 struct tileset *tileset;
537 int focus_unit_state = 0;
539 static bool tileset_update = FALSE;
542 static int fill_unit_type_sprite_array(const struct tileset *t,
543 struct drawn_sprite *sprs,
544 const struct unit_type *putype,
545 enum direction8 facing);
546 static int fill_unit_sprite_array(const struct tileset *t,
547 struct drawn_sprite *sprs,
548 const struct unit *punit,
549 bool stack, bool backdrop);
550 static bool load_river_sprites(struct tileset *t,
551 struct river_sprites *store, const char *tag_pfx);
553 static void tileset_setup_base(struct tileset *t,
554 const struct extra_type *pextra);
555 static void tileset_setup_road(struct tileset *t,
556 struct extra_type *pextra);
558 static bool is_extra_drawing_enabled(struct extra_type *pextra);
560 static int fill_basic_road_sprite_array(const struct tileset *t,
561 struct drawn_sprite *sprs,
562 const struct extra_type *pextra);
563 static int fill_basic_base_sprite_array(const struct tileset *t,
564 struct drawn_sprite *sprs,
565 const struct extra_type *pextra);
567 static void tileset_player_free(struct tileset *t, int plrid);
569 /****************************************************************************
570 Called when ever there's problem in ruleset/tileset compatibility
571 ****************************************************************************/
572 void tileset_error(enum log_level level, const char *format, ...)
574 char buf[2048];
575 va_list args;
577 va_start(args, format);
578 fc_vsnprintf(buf, sizeof(buf), format, args);
579 va_end(args);
581 log_base(level, "%s", buf);
583 if (level <= LOG_NORMAL) {
584 show_tileset_error(buf);
587 if (level == LOG_FATAL) {
588 exit(EXIT_FAILURE);
592 /****************************************************************************
593 Create a new drawing data.
594 ****************************************************************************/
595 static struct drawing_data *drawing_data_new(void)
597 struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
599 draw->name = NULL;
601 return draw;
604 /****************************************************************************
605 Free a drawing data.
606 ****************************************************************************/
607 static void drawing_data_destroy(struct drawing_data *draw)
609 int i;
611 fc_assert_ret(NULL != draw);
613 if (draw->name != NULL) {
614 free(draw->name);
616 for (i = 0; i < 4; i++) {
617 if (draw->blend[i]) {
618 free_sprite(draw->blend[i]);
621 for (i = 0; i < draw->num_layers; i++) {
622 int vec_size = sprite_vector_size(&draw->layer[i].allocated);
623 int j;
625 for (j = 0; j < vec_size; j++) {
626 free_sprite(draw->layer[i].allocated.p[j]);
629 sprite_vector_free(&draw->layer[i].base);
630 sprite_vector_free(&draw->layer[i].allocated);
631 free(draw->layer[i].cells);
633 free(draw);
636 /****************************************************************************
637 Return the name of the given tileset.
638 ****************************************************************************/
639 const char *tileset_basename(const struct tileset *t)
641 return t->name;
644 /****************************************************************************
645 Return whether the current tileset is isometric.
646 ****************************************************************************/
647 bool tileset_is_isometric(const struct tileset *t)
649 return t->type == TS_ISOMETRIC;
652 /****************************************************************************
653 Return the hex_width of the current tileset. For iso-hex tilesets this
654 value will be > 0 and is_isometric will be set.
655 ****************************************************************************/
656 int tileset_hex_width(const struct tileset *t)
658 return t->hex_width;
661 /****************************************************************************
662 Return the hex_height of the current tileset. For hex tilesets this
663 value will be > 0 and is_isometric will be set.
664 ****************************************************************************/
665 int tileset_hex_height(const struct tileset *t)
667 return t->hex_height;
670 /****************************************************************************
671 Return the tile width of the current tileset. This is the tesselation
672 width of the tiled plane. This means it's the width of the bounding box
673 of the basic map tile.
675 For best results:
676 - The value should be even (or a multiple of 4 in iso-view).
677 - In iso-view, the width should be twice the height (to give a
678 perspective of 30 degrees above the horizon).
679 - In non-iso-view, width and height should be equal (overhead
680 perspective).
681 - In hex or iso-hex view, remember this is the tesselation vector.
682 hex_width and hex_height then give the size of the side of the
683 hexagon. Calculating the dimensions of a "regular" hexagon or
684 iso-hexagon may be tricky.
685 However these requirements are not absolute and callers should not
686 depend on them (although some do).
687 ****************************************************************************/
688 int tileset_tile_width(const struct tileset *t)
690 return t->normal_tile_width;
693 /****************************************************************************
694 Return the tile height of the current tileset. This is the tesselation
695 height of the tiled plane. This means it's the height of the bounding box
696 of the basic map tile.
698 See also tileset_tile_width.
699 ****************************************************************************/
700 int tileset_tile_height(const struct tileset *t)
702 return t->normal_tile_height;
705 /****************************************************************************
706 Return the full tile width of the current tileset. This is the maximum
707 width that any mapview sprite will have.
709 Note: currently this is always equal to the tile width.
710 ****************************************************************************/
711 int tileset_full_tile_width(const struct tileset *t)
713 return t->full_tile_width;
716 /****************************************************************************
717 Return the full tile height of the current tileset. This is the maximum
718 height that any mapview sprite will have. This may be greater than the
719 tile width in which case the extra area is above the "normal" tile.
721 Some callers assume the full height is 50% larger than the height in
722 iso-view, and equal in non-iso view.
723 ****************************************************************************/
724 int tileset_full_tile_height(const struct tileset *t)
726 return t->full_tile_height;
729 /****************************************************************************
730 Return the unit tile width of the current tileset.
731 ****************************************************************************/
732 int tileset_unit_width(const struct tileset *t)
734 return t->unit_tile_width;
737 /****************************************************************************
738 Return the unit tile height of the current tileset.
739 ****************************************************************************/
740 int tileset_unit_height(const struct tileset *t)
742 return t->unit_tile_height;
745 /****************************************************************************
746 Calculate the height of a unit upkeep icons.
747 ****************************************************************************/
748 static int calculate_max_upkeep_height(const struct tileset *t)
750 int i;
751 int max = 0;
753 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
754 if (t->sprites.upkeep.unhappy[i] != NULL) {
755 int width, height;
757 /* TODO: We want only height, getting the width might waste CPU
758 * depending on gui-specific implementation. */
759 get_sprite_dimensions(t->sprites.upkeep.unhappy[i], &width, &height);
761 max = MAX(max, height);
765 output_type_iterate(o) {
766 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
767 if (t->sprites.upkeep.output[o][i] != NULL) {
768 int width, height;
770 /* TODO: We want only height, getting the width might waste CPU
771 * depending on gui-specific implementation. */
772 get_sprite_dimensions(t->sprites.upkeep.output[o][i], &width, &height);
774 max = MAX(max, height);
777 } output_type_iterate_end;
779 return max;
782 /****************************************************************************
783 Get the height of a unit upkeep icons.
784 ****************************************************************************/
785 static int tileset_upkeep_height(const struct tileset *t)
787 /* Return cached value */
788 return t->max_upkeep_height;
791 /****************************************************************************
792 Suitable canvas height for a unit icon that includes upkeep sprites.
793 ****************************************************************************/
794 int tileset_unit_with_upkeep_height(const struct tileset *t)
796 int uk_bottom = tileset_unit_layout_offset_y(tileset) + tileset_upkeep_height(tileset);
797 int u_bottom = tileset_unit_height(tileset);
799 return MAX(uk_bottom, u_bottom);
802 /****************************************************************************
803 Suitable canvas height for a unit icon that includes upkeep sprites,
804 using small space layout.
805 ****************************************************************************/
806 int tileset_unit_with_small_upkeep_height(const struct tileset *t)
808 return tileset_unit_layout_small_offset_y(tileset) + tileset_upkeep_height(tileset);
811 /****************************************************************************
812 Offset to layout extra unit sprites, such as upkeep.
813 ****************************************************************************/
814 int tileset_unit_layout_offset_y(const struct tileset *t)
816 return t->unit_upkeep_offset_y;
819 /****************************************************************************
820 Offset to layout extra unit sprites, such as upkeep, requesting small
821 space layout.
822 ****************************************************************************/
823 int tileset_unit_layout_small_offset_y(const struct tileset *t)
825 return t->unit_upkeep_small_offset_y;
828 /****************************************************************************
829 Return the small sprite width of the current tileset. The small sprites
830 are used for various theme graphics (e.g., citymap citizens/specialists
831 as well as panel indicator icons).
832 ****************************************************************************/
833 int tileset_small_sprite_width(const struct tileset *t)
835 return t->small_sprite_width;
838 /****************************************************************************
839 Return the offset from the origin of the city tile at which to place the
840 city bar text.
841 ****************************************************************************/
842 int tileset_citybar_offset_y(const struct tileset *t)
844 return t->citybar_offset_y;
847 /****************************************************************************
848 Return the offset from the origin of the tile at which to place the
849 label text.
850 ****************************************************************************/
851 int tileset_tilelabel_offset_y(const struct tileset *t)
853 return t->tilelabel_offset_y;
856 /****************************************************************************
857 Return the small sprite height of the current tileset. The small sprites
858 are used for various theme graphics (e.g., citymap citizens/specialists
859 as well as panel indicator icons).
860 ****************************************************************************/
861 int tileset_small_sprite_height(const struct tileset *t)
863 return t->small_sprite_height;
866 /****************************************************************************
867 Return the path within the data directories where the main intro graphics
868 file can be found. (It is left up to the GUI code to load and unload this
869 file.)
870 ****************************************************************************/
871 const char *tileset_main_intro_filename(const struct tileset *t)
873 return t->main_intro_filename;
876 /****************************************************************************
877 Return the path within the data directories where the mini intro graphics
878 file can be found. (It is left up to the GUI code to load and unload this
879 file.)
880 ****************************************************************************/
881 const char *tileset_mini_intro_filename(const struct tileset *t)
883 return t->minimap_intro_filename;
886 /****************************************************************************
887 Return the number of possible colors for city overlays.
888 ****************************************************************************/
889 int tileset_num_city_colors(const struct tileset *t)
891 return t->sprites.city.worked_tile_overlay.size;
894 /****************************************************************************
895 Return TRUE if the client will use the code to generate the fog.
896 ****************************************************************************/
897 bool tileset_use_hard_coded_fog(const struct tileset *t)
899 return FOG_AUTO == t->fogstyle;
902 /**************************************************************************
903 Initialize.
904 **************************************************************************/
905 static struct tileset *tileset_new(void)
907 struct tileset *t = fc_calloc(1, sizeof(*t));
909 t->specfiles = specfile_list_new();
910 t->small_sprites = small_sprite_list_new();
911 return t;
914 /**************************************************************************
915 Return the tileset name of the direction. This is similar to
916 dir_get_name but you shouldn't change this or all tilesets will break.
917 **************************************************************************/
918 static const char *dir_get_tileset_name(enum direction8 dir)
920 switch (dir) {
921 case DIR8_NORTH:
922 return "n";
923 case DIR8_NORTHEAST:
924 return "ne";
925 case DIR8_EAST:
926 return "e";
927 case DIR8_SOUTHEAST:
928 return "se";
929 case DIR8_SOUTH:
930 return "s";
931 case DIR8_SOUTHWEST:
932 return "sw";
933 case DIR8_WEST:
934 return "w";
935 case DIR8_NORTHWEST:
936 return "nw";
938 log_error("Wrong direction8 variant: %d.", dir);
939 return "";
942 /****************************************************************************
943 Return TRUE iff the dir is valid in this tileset.
944 ****************************************************************************/
945 static bool is_valid_tileset_dir(const struct tileset *t,
946 enum direction8 dir)
948 if (t->hex_width > 0) {
949 return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
950 } else if (t->hex_height > 0) {
951 return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
952 } else {
953 return TRUE;
957 /****************************************************************************
958 Return TRUE iff the dir is cardinal in this tileset.
960 "Cardinal", in this sense, means that a tile will share a border with
961 another tile in the direction rather than sharing just a single vertex.
962 ****************************************************************************/
963 static bool is_cardinal_tileset_dir(const struct tileset *t,
964 enum direction8 dir)
966 if (t->hex_width > 0 || t->hex_height > 0) {
967 return is_valid_tileset_dir(t, dir);
968 } else {
969 return (dir == DIR8_NORTH || dir == DIR8_EAST
970 || dir == DIR8_SOUTH || dir == DIR8_WEST);
974 /**********************************************************************
975 Convert properties of the actual topology to an index of different
976 tileset topology types.
977 ***********************************************************************/
978 static int ts_topology_index(int actual_topology)
980 int idx;
982 if ((actual_topology & TF_HEX)
983 && (actual_topology & TF_ISO)) {
984 idx = TS_TOPO_ISOHEX;
985 } else if (actual_topology & TF_ISO) {
986 idx = TS_TOPO_ISO;
987 } else if (actual_topology & TF_HEX) {
988 idx = TS_TOPO_HEX;
989 } else {
990 idx = TS_TOPO_OVERHEAD;
993 return idx;
996 /**********************************************************************
997 Returns a static list of tilesets available on the system by
998 searching all data directories for files matching TILESPEC_SUFFIX.
999 ***********************************************************************/
1000 const struct strvec *get_tileset_list(const struct option *poption)
1002 static struct strvec *tilesets[4] = { NULL, NULL, NULL, NULL };
1003 int topo = option_get_cb_data(poption);
1004 int idx;
1006 idx = ts_topology_index(topo);
1008 fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), NULL);
1010 if (tilesets[idx] == NULL) {
1011 /* Note: this means you must restart the client after installing a new
1012 tileset. */
1013 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1015 tilesets[idx] = strvec_new();
1016 strvec_iterate(list, file) {
1017 struct tileset *t = tileset_read_toplevel(file, FALSE, topo);
1019 if (t) {
1020 strvec_append(tilesets[idx], file);
1021 tileset_free(t);
1023 } strvec_iterate_end;
1024 strvec_destroy(list);
1027 return tilesets[idx];
1030 /**********************************************************************
1031 Gets full filename for tilespec file, based on input name.
1032 Returned data is allocated, and freed by user as required.
1033 Input name may be null, in which case uses default.
1034 Falls back to default if can't find specified name;
1035 dies if can't find default.
1036 ***********************************************************************/
1037 static char *tilespec_fullname(const char *tileset_name)
1039 if (tileset_name) {
1040 char fname[strlen(tileset_name) + strlen(TILESPEC_SUFFIX) + 1];
1041 const char *dname;
1043 fc_snprintf(fname, sizeof(fname),
1044 "%s%s", tileset_name, TILESPEC_SUFFIX);
1046 dname = fileinfoname(get_data_dirs(), fname);
1048 if (dname) {
1049 return fc_strdup(dname);
1053 return NULL;
1056 /**********************************************************************
1057 Checks options in filename match what we require and support.
1058 Die if not.
1059 'which' should be "tilespec" or "spec".
1060 ***********************************************************************/
1061 static bool check_tilespec_capabilities(struct section_file *file,
1062 const char *which,
1063 const char *us_capstr,
1064 const char *filename,
1065 bool verbose)
1067 enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
1069 const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
1071 if (NULL == file_capstr) {
1072 log_base(level, "\"%s\": %s file doesn't have a capability string",
1073 filename, which);
1074 return FALSE;
1076 if (!has_capabilities(us_capstr, file_capstr)) {
1077 log_base(level, "\"%s\": %s file appears incompatible:",
1078 filename, which);
1079 log_base(level, " datafile options: %s", file_capstr);
1080 log_base(level, " supported options: %s", us_capstr);
1081 return FALSE;
1083 if (!has_capabilities(file_capstr, us_capstr)) {
1084 log_base(level, "\"%s\": %s file requires option(s) "
1085 "that client doesn't support:", filename, which);
1086 log_base(level, " datafile options: %s", file_capstr);
1087 log_base(level, " supported options: %s", us_capstr);
1088 return FALSE;
1091 return TRUE;
1094 /**********************************************************************
1095 Frees the tilespec toplevel data, in preparation for re-reading it.
1097 See tilespec_read_toplevel().
1098 ***********************************************************************/
1099 static void tileset_free_toplevel(struct tileset *t)
1101 int i, j;
1103 if (t->main_intro_filename) {
1104 free(t->main_intro_filename);
1105 t->main_intro_filename = NULL;
1107 if (t->minimap_intro_filename) {
1108 free(t->minimap_intro_filename);
1109 t->minimap_intro_filename = NULL;
1112 if (t->preferred_themes) {
1113 for (i = 0; i < t->num_preferred_themes; i++) {
1114 free(t->preferred_themes[i]);
1116 free(t->preferred_themes);
1117 t->preferred_themes = NULL;
1119 t->num_preferred_themes = 0;
1121 if (t->tile_hash) {
1122 drawing_hash_destroy(t->tile_hash);
1123 t->tile_hash = NULL; /* Helpful for sanity. */
1125 if (t->estyle_hash) {
1126 estyle_hash_destroy(t->estyle_hash);
1127 t->estyle_hash = NULL;
1129 for (i = 0; i < ESTYLE_COUNT; i++) {
1130 if (t->style_lists[i] != NULL) {
1131 extra_type_list_destroy(t->style_lists[i]);
1132 t->style_lists[i] = NULL;
1136 if (t->flagged_bases_list != NULL) {
1137 extra_type_list_destroy(t->flagged_bases_list);
1138 t->flagged_bases_list = NULL;
1141 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1142 struct tileset_layer *tslp = &t->layers[i];
1144 if (tslp->match_types) {
1145 for (j = 0; j < tslp->match_count; j++) {
1146 free(tslp->match_types[j]);
1148 free(tslp->match_types);
1149 tslp->match_types = NULL;
1153 if (t->color_system) {
1154 color_system_free(t->color_system);
1155 t->color_system = NULL;
1158 if (t->summary != NULL) {
1159 free(t->summary);
1160 t->summary = NULL;
1162 if (t->description != NULL) {
1163 free(t->description);
1164 t->description = NULL;
1168 /**************************************************************************
1169 Clean up.
1170 **************************************************************************/
1171 void tileset_free(struct tileset *t)
1173 int i;
1175 tileset_free_tiles(t);
1176 tileset_free_toplevel(t);
1177 for (i = 0; i < ARRAY_SIZE(t->sprites.player); i++) {
1178 tileset_player_free(t, i);
1180 specfile_list_destroy(t->specfiles);
1181 small_sprite_list_destroy(t->small_sprites);
1182 free(t);
1185 /**********************************************************************
1186 Read a new tilespec in when first starting the game.
1188 Call this function with the (guessed) name of the tileset, when
1189 starting the client.
1190 ***********************************************************************/
1191 void tilespec_try_read(const char *tileset_name, bool verbose, int topo_id,
1192 bool global_default)
1194 if (tileset_name == NULL
1195 || !(tileset = tileset_read_toplevel(tileset_name, verbose, topo_id))) {
1196 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1198 strvec_iterate(list, file) {
1199 struct tileset *t = tileset_read_toplevel(file, FALSE, topo_id);
1201 if (t) {
1202 if (!tileset) {
1203 tileset = t;
1204 } else if (t->priority > tileset->priority
1205 || (topo_id >= 0
1206 && tileset_topo_index(tileset) != tileset_topo_index(t))) {
1207 tileset_free(tileset);
1208 tileset = t;
1209 } else {
1210 tileset_free(t);
1213 } strvec_iterate_end;
1214 strvec_destroy(list);
1216 if (!tileset) {
1217 tileset_error(LOG_FATAL, _("No usable default tileset found, aborting!"));
1220 log_verbose("Trying tileset \"%s\".", tileset->name);
1222 option_set_default_ts(tileset);
1224 if (global_default) {
1225 sz_strlcpy(gui_options.default_tileset_name, tileset_basename(tileset));
1229 /**********************************************************************
1230 Read a new tilespec in from scratch.
1232 Unlike the initial reading code, which reads pieces one at a time,
1233 this gets rid of the old data and reads in the new all at once. If the
1234 new tileset fails to load the old tileset may be reloaded; otherwise the
1235 client will exit. If a NULL name is given the current tileset will be
1236 reread.
1238 It will also call the necessary functions to redraw the graphics.
1239 ***********************************************************************/
1240 void tilespec_reread(const char *new_tileset_name, bool game_fully_initialized)
1242 int id;
1243 struct tile *center_tile;
1244 enum client_states state = client_state();
1245 const char *name = new_tileset_name ? new_tileset_name : tileset->name;
1246 char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1247 int i;
1249 /* Make local copies since these values may be freed down below */
1250 sz_strlcpy(tileset_name, name);
1251 sz_strlcpy(old_name, tileset->name);
1253 log_normal(_("Loading tileset \"%s\"."), tileset_name);
1255 /* Step 0: Record old data.
1257 * We record the current mapcanvas center, etc.
1259 center_tile = get_center_tile_mapcanvas();
1261 /* Step 1: Cleanup.
1263 * We free all old data in preparation for re-reading it.
1265 tileset_free_tiles(tileset);
1266 tileset_free_toplevel(tileset);
1267 for (i = 0; i < ARRAY_SIZE(tileset->sprites.player); i++) {
1268 tileset_player_free(tileset, i);
1271 /* Step 2: Read.
1273 * We read in the new tileset. This should be pretty straightforward.
1275 if (!(tileset = tileset_read_toplevel(tileset_name, FALSE, -1))) {
1276 if (!(tileset = tileset_read_toplevel(old_name, FALSE, -1))) {
1277 /* Always fails. */
1278 fc_assert_exit_msg(NULL != tileset,
1279 "Failed to re-read the currently loaded tileset.");
1282 tileset_load_tiles(tileset);
1283 if (game_fully_initialized) {
1284 tileset_use_preferred_theme(tileset);
1287 if (game_fully_initialized) {
1288 tileset_background_init(tileset);
1289 players_iterate(pplayer) {
1290 tileset_player_init(tileset, pplayer);
1291 } players_iterate_end;
1292 boot_help_texts(); /* "About Current Tileset" */
1295 /* Step 3: Setup
1297 * This is a seriously sticky problem. On startup, we build a hash
1298 * from all the sprite data. Then, when we connect to a server, the
1299 * server sends us ruleset data a piece at a time and we use this data
1300 * to assemble the sprite structures. But if we change while connected
1301 * we have to reassemble all of these. This should just involve
1302 * calling tilespec_setup_*** on everything. But how do we tell what
1303 * "everything" is?
1305 * The below code just does things straightforwardly, by setting up
1306 * each possible sprite again. Hopefully it catches everything, and
1307 * doesn't mess up too badly if we change tilesets while not connected
1308 * to a server.
1310 if (!game.client.ruleset_ready) {
1311 /* The ruleset data is not sent until this point. */
1312 return;
1315 if (!tileset_map_topo_compatible(game.map.topology_id, tileset)) {
1316 tileset_error(LOG_NORMAL, _("Map topology and tileset incompatible."));
1319 terrain_type_iterate(pterrain) {
1320 tileset_setup_tile_type(tileset, pterrain);
1321 } terrain_type_iterate_end;
1322 resource_type_iterate(presource) {
1323 tileset_setup_resource(tileset, presource);
1324 } resource_type_iterate_end;
1325 unit_type_iterate(punittype) {
1326 tileset_setup_unit_type(tileset, punittype);
1327 } unit_type_iterate_end;
1328 governments_iterate(gov) {
1329 tileset_setup_government(tileset, gov);
1330 } governments_iterate_end;
1331 extra_type_iterate(pextra) {
1332 tileset_setup_extra(tileset, pextra);
1333 } extra_type_iterate_end;
1334 nations_iterate(pnation) {
1335 tileset_setup_nation_flag(tileset, pnation);
1336 } nations_iterate_end;
1337 improvement_iterate(pimprove) {
1338 tileset_setup_impr_type(tileset, pimprove);
1339 } improvement_iterate_end;
1340 advance_iterate(A_FIRST, padvance) {
1341 tileset_setup_tech_type(tileset, padvance);
1342 } advance_iterate_end;
1343 specialist_type_iterate(sp) {
1344 tileset_setup_specialist_type(tileset, sp);
1345 } specialist_type_iterate_end;
1347 for (id = 0; id < game.control.styles_count; id++) {
1348 tileset_setup_city_tiles(tileset, id);
1351 if (state < C_S_RUNNING) {
1352 /* Below redraws do not apply before this. */
1353 return;
1356 /* Step 4: Draw.
1358 * Do any necessary redraws.
1360 generate_citydlg_dimensions();
1361 tileset_changed();
1362 can_slide = FALSE;
1363 center_tile_mapcanvas(center_tile);
1364 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1365 * drawing we might not get one. Of course this is slower. */
1366 update_map_canvas_visible();
1367 can_slide = TRUE;
1370 /**************************************************************************
1371 This is merely a wrapper for tilespec_reread (above) for use in
1372 options.c and the client local options dialog.
1373 **************************************************************************/
1374 void tilespec_reread_callback(struct option *poption)
1376 const char *tileset_name;
1377 enum client_states state = client_state();
1379 if ((state == C_S_RUNNING || state == C_S_OVER)
1380 && option_get_cb_data(poption) != (game.map.topology_id & (TF_ISO | TF_HEX))) {
1381 /* Changed option was not for current topology */
1382 return;
1385 tileset_name = option_str_get(poption);
1387 /* As it's going to be 'current' tileset, make it global default if
1388 * options saved. */
1389 sz_strlcpy(gui_options.default_tileset_name, tileset_name);
1391 fc_assert_ret(NULL != tileset_name && tileset_name[0] != '\0');
1392 tileset_update = TRUE;
1393 tilespec_reread(tileset_name, client.conn.established);
1394 tileset_update = FALSE;
1395 menus_init();
1398 /**************************************************************************
1400 **************************************************************************/
1401 void tilespec_reread_frozen_refresh(const char *tname)
1403 tileset_update = TRUE;
1404 tilespec_reread(tname, TRUE);
1405 tileset_update = FALSE;
1406 menus_init();
1409 /**************************************************************************
1410 Loads the given graphics file (found in the data path) into a newly
1411 allocated sprite.
1412 **************************************************************************/
1413 static struct sprite *load_gfx_file(const char *gfx_filename)
1415 const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
1416 struct sprite *s;
1418 /* Try out all supported file extensions to find one that works. */
1419 while ((gfx_fileext = *gfx_fileexts++)) {
1420 const char *real_full_name;
1421 char full_name[strlen(gfx_filename) + strlen(".")
1422 + strlen(gfx_fileext) + 1];
1424 sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
1425 if ((real_full_name = fileinfoname(get_data_dirs(), full_name))) {
1426 log_debug("trying to load gfx file \"%s\".", real_full_name);
1427 s = load_gfxfile(real_full_name);
1428 if (s) {
1429 return s;
1434 log_error("Could not load gfx file \"%s\".", gfx_filename);
1435 return NULL;
1438 /**************************************************************************
1439 Ensure that the big sprite of the given spec file is loaded.
1440 **************************************************************************/
1441 static void ensure_big_sprite(struct specfile *sf)
1443 struct section_file *file;
1444 const char *gfx_filename;
1446 if (sf->big_sprite) {
1447 /* Looks like it's already loaded. */
1448 return;
1451 /* Otherwise load it. The big sprite will sometimes be freed and will have
1452 * to be reloaded, but most of the time it's just loaded once, the small
1453 * sprites are extracted, and then it's freed. */
1454 if (!(file = secfile_load(sf->file_name, TRUE))) {
1455 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1458 if (!check_tilespec_capabilities(file, "spec",
1459 SPEC_CAPSTR, sf->file_name, TRUE)) {
1460 tileset_error(LOG_FATAL, _("Incompatible tileset capabilities"));
1463 gfx_filename = secfile_lookup_str(file, "file.gfx");
1465 sf->big_sprite = load_gfx_file(gfx_filename);
1467 if (!sf->big_sprite) {
1468 tileset_error(LOG_FATAL, _("Could not load gfx file for the spec file \"%s\"."),
1469 sf->file_name);
1471 secfile_destroy(file);
1474 /**************************************************************************
1475 Scan all sprites declared in the given specfile. This means that the
1476 positions of the sprites in the big_sprite are saved in the
1477 small_sprite structs.
1478 **************************************************************************/
1479 static void scan_specfile(struct tileset *t, struct specfile *sf,
1480 bool duplicates_ok)
1482 struct section_file *file;
1483 struct section_list *sections;
1484 int i;
1486 if (!(file = secfile_load(sf->file_name, TRUE))) {
1487 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1489 if (!check_tilespec_capabilities(file, "spec",
1490 SPEC_CAPSTR, sf->file_name, TRUE)) {
1491 tileset_error(LOG_FATAL, _("Specfile %s has incompatible capabilities"), sf->file_name);
1494 /* Currently unused */
1495 (void) secfile_entry_lookup(file, "info.artists");
1497 /* Not used here */
1498 (void) secfile_entry_lookup(file, "file.gfx");
1500 if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1501 section_list_iterate(sections, psection) {
1502 int j, k;
1503 int x_top_left, y_top_left, dx, dy;
1504 int pixel_border_x;
1505 int pixel_border_y;
1506 const char *sec_name = section_name(psection);
1508 pixel_border_x = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1509 sec_name);
1510 pixel_border_y = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_y",
1511 sec_name);
1512 pixel_border_x = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_x",
1513 sec_name);
1515 if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1516 || !secfile_lookup_int(file, &y_top_left,
1517 "%s.y_top_left", sec_name)
1518 || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1519 || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1520 log_error("Grid \"%s\" invalid: %s", sec_name, secfile_error());
1521 continue;
1524 j = -1;
1525 while (NULL != secfile_entry_lookup(file, "%s.tiles%d.tag",
1526 sec_name, ++j)) {
1527 struct small_sprite *ss;
1528 int row, column;
1529 int xr, yb;
1530 const char **tags;
1531 size_t num_tags;
1532 int hot_x, hot_y;
1534 if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1535 || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1536 sec_name, j)
1537 || !(tags = secfile_lookup_str_vec(file, &num_tags,
1538 "%s.tiles%d.tag",
1539 sec_name, j))) {
1540 log_error("Small sprite \"%s.tiles%d\" invalid: %s",
1541 sec_name, j, secfile_error());
1542 continue;
1544 hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1545 sec_name, j);
1546 hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1547 sec_name, j);
1549 /* there must be at least 1 because of the while(): */
1550 fc_assert_action(num_tags > 0, continue);
1552 xr = x_top_left + (dx + pixel_border_x) * column;
1553 yb = y_top_left + (dy + pixel_border_y) * row;
1555 ss = fc_malloc(sizeof(*ss));
1556 ss->ref_count = 0;
1557 ss->file = NULL;
1558 ss->x = xr;
1559 ss->y = yb;
1560 ss->width = dx;
1561 ss->height = dy;
1562 ss->sf = sf;
1563 ss->sprite = NULL;
1564 ss->hot_x = hot_x;
1565 ss->hot_y = hot_y;
1567 small_sprite_list_prepend(t->small_sprites, ss);
1569 if (!duplicates_ok) {
1570 for (k = 0; k < num_tags; k++) {
1571 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1572 log_error("warning: already have a sprite for \"%s\".",
1573 tags[k]);
1576 } else {
1577 for (k = 0; k < num_tags; k++) {
1578 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1582 free(tags);
1583 tags = NULL;
1585 } section_list_iterate_end;
1586 section_list_destroy(sections);
1589 /* Load "extra" sprites. Each sprite is one file. */
1590 i = -1;
1591 while (NULL != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1592 struct small_sprite *ss;
1593 const char **tags;
1594 const char *filename;
1595 size_t num_tags, k;
1596 int hot_x, hot_y;
1598 if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1599 "extra.sprites%d.tag", i))
1600 || !(filename = secfile_lookup_str(file,
1601 "extra.sprites%d.file", i))) {
1602 log_error("Extra sprite \"extra.sprites%d\" invalid: %s",
1603 i, secfile_error());
1604 continue;
1606 hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1607 hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1609 ss = fc_malloc(sizeof(*ss));
1610 ss->ref_count = 0;
1611 ss->file = fc_strdup(filename);
1612 ss->sf = NULL;
1613 ss->sprite = NULL;
1614 ss->hot_x = hot_x;
1615 ss->hot_y = hot_y;
1617 small_sprite_list_prepend(t->small_sprites, ss);
1619 if (!duplicates_ok) {
1620 for (k = 0; k < num_tags; k++) {
1621 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1622 log_error("warning: already have a sprite for \"%s\".", tags[k]);
1625 } else {
1626 for (k = 0; k < num_tags; k++) {
1627 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1630 free(tags);
1633 secfile_check_unused(file);
1634 secfile_destroy(file);
1637 /**********************************************************************
1638 Returns the correct name of the gfx file (with path and extension)
1639 Must be free'd when no longer used
1640 ***********************************************************************/
1641 static char *tilespec_gfx_filename(const char *gfx_filename)
1643 const char *gfx_current_fileext;
1644 const char **gfx_fileexts = gfx_fileextensions();
1646 while ((gfx_current_fileext = *gfx_fileexts++)) {
1647 const char *real_full_name;
1648 char *full_name =
1649 fc_malloc(strlen(gfx_filename) + strlen(".")
1650 + strlen(gfx_current_fileext) + 1);
1652 sprintf(full_name, "%s.%s", gfx_filename, gfx_current_fileext);
1654 real_full_name = fileinfoname(get_data_dirs(), full_name);
1655 free(full_name);
1656 if (real_full_name) {
1657 return fc_strdup(real_full_name);
1661 tileset_error(LOG_FATAL, _("Couldn't find a supported gfx file extension for \"%s\"."),
1662 gfx_filename);
1664 return NULL;
1667 /**********************************************************************
1668 Determine the sprite_type string.
1669 ***********************************************************************/
1670 static int check_sprite_type(const char *sprite_type, const char *tile_section)
1672 if (fc_strcasecmp(sprite_type, "corner") == 0) {
1673 return CELL_CORNER;
1675 if (fc_strcasecmp(sprite_type, "single") == 0) {
1676 return CELL_WHOLE;
1678 if (fc_strcasecmp(sprite_type, "whole") == 0) {
1679 return CELL_WHOLE;
1681 log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1682 return CELL_WHOLE;
1685 /**********************************************************************
1686 Finds and reads the toplevel tilespec file based on given name.
1687 Sets global variables, including tile sizes and full names for
1688 intro files.
1689 topology_id of -1 means any topology is acceptable.
1690 ***********************************************************************/
1691 struct tileset *tileset_read_toplevel(const char *tileset_name, bool verbose,
1692 int topology_id)
1694 struct section_file *file;
1695 char *fname;
1696 const char *c;
1697 int i;
1698 size_t num_spec_files;
1699 const char **spec_filenames;
1700 size_t num_preferred_themes;
1701 struct section_list *sections = NULL;
1702 const char *file_capstr;
1703 bool duplicates_ok, is_hex;
1704 enum direction8 dir;
1705 struct tileset *t = NULL;
1706 const char *extraname;
1707 const char *tstr;
1708 int topo;
1710 fname = tilespec_fullname(tileset_name);
1711 if (!fname) {
1712 if (verbose) {
1713 log_error("Can't find tileset \"%s\".", tileset_name);
1715 return NULL;
1717 log_verbose("tilespec file is \"%s\".", fname);
1719 if (!(file = secfile_load(fname, TRUE))) {
1720 log_error("Could not open '%s':\n%s", fname, secfile_error());
1721 free(fname);
1722 return NULL;
1725 if (!check_tilespec_capabilities(file, "tilespec",
1726 TILESPEC_CAPSTR, fname, verbose)) {
1727 secfile_destroy(file);
1728 free(fname);
1729 return NULL;
1732 t = tileset_new();
1733 file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1734 duplicates_ok = (NULL != file_capstr
1735 && has_capabilities("+duplicates_ok", file_capstr));
1737 tstr = secfile_lookup_str(file, "tilespec.name");
1738 /* Tileset name found */
1739 sz_strlcpy(t->given_name, tstr);
1740 tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1741 if (tstr[0] != '\0') {
1742 /* Tileset version found */
1743 sz_strlcpy(t->version, tstr);
1744 } else {
1745 /* No version information */
1746 t->version[0] = '\0';
1749 tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
1750 if (tstr[0] != '\0') {
1751 int len;
1753 /* Tileset summary found */
1754 len = strlen(tstr);
1755 t->summary = fc_malloc(len + 1);
1756 fc_strlcpy(t->summary, tstr, len + 1);
1757 } else {
1758 /* No summary */
1759 if (t->summary != NULL) {
1760 free(t->summary);
1761 t->summary = NULL;
1765 tstr = secfile_lookup_str_default(file, "", "tilespec.description");
1766 if (tstr[0] != '\0') {
1767 int len;
1769 /* Tileset description found */
1770 len = strlen(tstr);
1771 t->description = fc_malloc(len + 1);
1772 fc_strlcpy(t->description, tstr, len + 1);
1773 } else {
1774 /* No description */
1775 if (t->description != NULL) {
1776 free(t->description);
1777 t->description = NULL;
1781 sz_strlcpy(t->name, tileset_name);
1782 if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1783 || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1784 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1785 goto ON_ERROR;
1788 tstr = secfile_lookup_str(file, "tilespec.type");
1789 if (tstr == NULL) {
1790 log_error("Tileset \"%s\": no tileset type", t->name);
1791 goto ON_ERROR;
1794 t->type = ts_type_by_name(tstr, fc_strcasecmp);
1795 if (!ts_type_is_valid(t->type)) {
1796 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1797 goto ON_ERROR;
1800 if (t->type == TS_ISOMETRIC) {
1801 topo = TF_ISO;
1802 } else {
1803 topo = 0;
1806 if (t->type == TS_ISOMETRIC) {
1807 topo = TF_ISO;
1808 } else {
1809 topo = 0;
1812 /* Read hex-tileset information. */
1813 t->hex_width = t->hex_height = 0;
1814 if (is_hex) {
1815 int hex_side;
1817 if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1818 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1819 goto ON_ERROR;
1822 if (t->type == TS_ISOMETRIC) {
1823 t->hex_width = hex_side;
1824 } else {
1825 t->hex_height = hex_side;
1828 topo |= TF_HEX;
1830 /* Hex tilesets are drawn the same as isometric. */
1831 /* FIXME: There will be other legal values to be used with hex
1832 * tileset in the future, and this would just overwrite it. */
1833 t->type = TS_ISOMETRIC;
1836 if (topology_id >= 0 && topo != (topology_id & (TF_ISO | TF_HEX))) {
1837 /* Not of requested topology */
1838 goto ON_ERROR;
1841 t->ts_topo_idx = ts_topology_index(topo);
1843 if (!is_view_supported(t->type)) {
1844 log_normal(_("Client does not support %s tilesets."),
1845 _(ts_type_name(t->type)));
1846 log_normal(_("Using default tileset instead."));
1847 fc_assert(tileset_name != NULL);
1848 goto ON_ERROR;
1851 /* Create arrays of valid and cardinal tileset dirs. These depend
1852 * entirely on the tileset, not the topology. They are also in clockwise
1853 * rotational ordering. */
1854 t->num_valid_tileset_dirs = t->num_cardinal_tileset_dirs = 0;
1855 dir = DIR8_NORTH;
1856 do {
1857 if (is_valid_tileset_dir(t, dir)) {
1858 t->valid_tileset_dirs[t->num_valid_tileset_dirs] = dir;
1859 t->num_valid_tileset_dirs++;
1861 if (is_cardinal_tileset_dir(t, dir)) {
1862 t->cardinal_tileset_dirs[t->num_cardinal_tileset_dirs] = dir;
1863 t->num_cardinal_tileset_dirs++;
1866 dir = dir_cw(dir);
1867 } while (dir != DIR8_NORTH);
1868 fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
1869 t->num_index_valid = 1 << t->num_valid_tileset_dirs;
1870 t->num_index_cardinal = 1 << t->num_cardinal_tileset_dirs;
1872 if (!secfile_lookup_int(file, &t->normal_tile_width,
1873 "tilespec.normal_tile_width")
1874 || !secfile_lookup_int(file, &t->normal_tile_height,
1875 "tilespec.normal_tile_height")) {
1876 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1877 goto ON_ERROR;
1879 if (t->type == TS_ISOMETRIC) {
1880 t->full_tile_width = t->normal_tile_width;
1881 if (tileset_hex_height(t) > 0) {
1882 t->full_tile_height = t->normal_tile_height;
1883 } else {
1884 t->full_tile_height = 3 * t->normal_tile_height / 2;
1886 } else {
1887 t->full_tile_width = t->normal_tile_width;
1888 t->full_tile_height = t->normal_tile_height;
1890 t->unit_tile_width
1891 = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
1892 t->unit_tile_height
1893 = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
1894 if (!secfile_lookup_int(file, &t->small_sprite_width,
1895 "tilespec.small_tile_width")
1896 || !secfile_lookup_int(file, &t->small_sprite_height,
1897 "tilespec.small_tile_height")) {
1898 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1899 goto ON_ERROR;
1901 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1902 t->normal_tile_width, t->normal_tile_height,
1903 t->full_tile_width, t->full_tile_height,
1904 t->small_sprite_width, t->small_sprite_height);
1906 tstr = secfile_lookup_str(file, "tilespec.fog_style");
1907 if (tstr == NULL) {
1908 log_error("Tileset \"%s\": no fog_style", t->name);
1909 goto ON_ERROR;
1912 t->fogstyle = fog_style_by_name(tstr, fc_strcasecmp);
1913 if (!fog_style_is_valid(t->fogstyle)) {
1914 log_error("Tileset \"%s\": unknown fog_style \"%s\"", t->name, tstr);
1915 goto ON_ERROR;
1918 tstr = secfile_lookup_str(file, "tilespec.darkness_style");
1919 if (tstr == NULL) {
1920 log_error("Tileset \"%s\": no darkness_style", t->name);
1921 goto ON_ERROR;
1924 t->darkness_style = darkness_style_by_name(tstr, fc_strcasecmp);
1925 if (!darkness_style_is_valid(t->darkness_style)) {
1926 log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t->name, tstr);
1927 goto ON_ERROR;
1930 if (t->darkness_style == DARKNESS_ISORECT
1931 && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
1932 log_error("Invalid darkness style set in tileset \"%s\".", t->name);
1933 goto ON_ERROR;
1935 t->darkness_layer = secfile_lookup_int_default(file, 0, "tilespec.darkness_layer");
1936 if (t->darkness_layer < 0 || t->darkness_layer >= TERRAIN_LAYER_COUNT) {
1937 tileset_error(LOG_ERROR, "Invalid darkness layer %d in tileset \"%s\"",
1938 t->darkness_layer, t->name);
1939 goto ON_ERROR;
1942 if (!secfile_lookup_int(file, &t->unit_flag_offset_x,
1943 "tilespec.unit_flag_offset_x")
1944 || !secfile_lookup_int(file, &t->unit_flag_offset_y,
1945 "tilespec.unit_flag_offset_y")
1946 || !secfile_lookup_int(file, &t->city_flag_offset_x,
1947 "tilespec.city_flag_offset_x")
1948 || !secfile_lookup_int(file, &t->city_flag_offset_y,
1949 "tilespec.city_flag_offset_y")
1950 || !secfile_lookup_int(file, &t->unit_offset_x,
1951 "tilespec.unit_offset_x")
1952 || !secfile_lookup_int(file, &t->unit_offset_y,
1953 "tilespec.unit_offset_y")
1954 || !secfile_lookup_int(file, &t->activity_offset_x,
1955 "tilespec.activity_offset_x")
1956 || !secfile_lookup_int(file, &t->activity_offset_y,
1957 "tilespec.activity_offset_y")
1958 || !secfile_lookup_int(file, &t->city_offset_x,
1959 "tilespec.city_offset_x")
1960 || !secfile_lookup_int(file, &t->city_offset_y,
1961 "tilespec.city_offset_y")
1962 || !secfile_lookup_int(file, &t->citybar_offset_y,
1963 "tilespec.citybar_offset_y")
1964 || !secfile_lookup_int(file, &t->tilelabel_offset_y,
1965 "tilespec.tilelabel_offset_y")
1966 || !secfile_lookup_int(file, &t->occupied_offset_x,
1967 "tilespec.occupied_offset_x")
1968 || !secfile_lookup_int(file, &t->occupied_offset_y,
1969 "tilespec.occupied_offset_y")
1970 || !secfile_lookup_int(file, &t->city_names_font_size,
1971 "tilespec.city_names_font_size")
1972 || !secfile_lookup_int(file, &t->city_productions_font_size,
1973 "tilespec.city_productions_font_size")) {
1974 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1975 goto ON_ERROR;
1978 t->unit_upkeep_offset_y = secfile_lookup_int_default(file, tileset_tile_height(t),
1979 "tilespec.unit_upkeep_offset_y");
1980 t->unit_upkeep_small_offset_y = secfile_lookup_int_default(file, t->unit_upkeep_offset_y,
1981 "tilespec.unit_upkeep_small_offset_y");
1983 set_city_names_font_sizes(t->city_names_font_size,
1984 t->city_productions_font_size);
1986 c = secfile_lookup_str(file, "tilespec.main_intro_file");
1987 t->main_intro_filename = tilespec_gfx_filename(c);
1988 log_debug("intro file %s", t->main_intro_filename);
1990 c = secfile_lookup_str_default(file, NULL, "tilespec.minimap_intro_file");
1991 if (c == NULL) {
1992 t->minimap_intro_filename = NULL;
1993 } else {
1994 t->minimap_intro_filename = tilespec_gfx_filename(c);
1995 log_debug("radar file %s", t->minimap_intro_filename);
1998 /* Terrain layer info. */
1999 for (i = 0; i < MAX_NUM_LAYERS; i++) {
2000 struct tileset_layer *tslp = &t->layers[i];
2001 int j, k;
2003 tslp->match_types =
2004 (char **) secfile_lookup_str_vec(file, &tslp->match_count,
2005 "layer%d.match_types", i);
2006 for (j = 0; j < tslp->match_count; j++) {
2007 tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
2009 for (k = 0; k < j; k++) {
2010 if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
2011 tileset_error(LOG_FATAL, _("[layer%d] match_types: \"%s\" initial "
2012 "('%c') is not unique."),
2013 i, tslp->match_types[j], tslp->match_types[j][0]);
2014 /* FIXME: Returns NULL. */
2020 /* Tile drawing info. */
2021 sections = secfile_sections_by_name_prefix(file, TILE_SECTION_PREFIX);
2022 if (NULL == sections || 0 == section_list_size(sections)) {
2023 tileset_error(LOG_ERROR, _("No [%s] sections supported by tileset \"%s\"."),
2024 TILE_SECTION_PREFIX, fname);
2025 goto ON_ERROR;
2028 fc_assert(t->tile_hash == NULL);
2029 t->tile_hash = drawing_hash_new();
2031 section_list_iterate(sections, psection) {
2032 const char *sec_name = section_name(psection);
2033 struct drawing_data *draw = drawing_data_new();
2034 const char *sprite_type;
2035 int l;
2036 const char *terrain_name;
2038 terrain_name = secfile_lookup_str(file, "%s.tag", sec_name);
2040 if (terrain_name != NULL) {
2041 draw->name = fc_strdup(terrain_name);
2042 } else {
2043 tileset_error(LOG_ERROR, _("No terrain tag given in section [%s]."), sec_name);
2044 drawing_data_destroy(draw);
2045 goto ON_ERROR;
2048 draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
2049 sec_name);
2050 draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
2052 draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
2053 "%s.is_reversed",
2054 sec_name);
2055 draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
2056 sec_name);
2057 draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
2059 for (l = 0; l < draw->num_layers; l++) {
2060 struct drawing_layer *dlp = &draw->layer[l];
2061 struct tileset_layer *tslp = &t->layers[l];
2062 const char *match_type;
2063 const char **match_with;
2064 size_t count;
2066 dlp->is_tall
2067 = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
2068 sec_name, l);
2069 dlp->offset_x
2070 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
2071 sec_name, l);
2072 dlp->offset_y
2073 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
2074 sec_name, l);
2076 match_type = secfile_lookup_str_default(file, NULL,
2077 "%s.layer%d_match_type",
2078 sec_name, l);
2079 if (match_type) {
2080 int j;
2082 /* Determine our match_type. */
2083 for (j = 0; j < tslp->match_count; j++) {
2084 if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
2085 break;
2088 if (j >= tslp->match_count) {
2089 log_error("[%s] invalid match_type \"%s\".", sec_name, match_type);
2090 } else {
2091 dlp->match_index[dlp->match_indices++] = j;
2095 match_with = secfile_lookup_str_vec(file, &count,
2096 "%s.layer%d_match_with",
2097 sec_name, l);
2098 if (match_with) {
2099 int j, k;
2101 if (count > MAX_NUM_MATCH_WITH) {
2102 log_error("[%s] match_with has too many types (%d, max %d)",
2103 sec_name, (int) count, MAX_NUM_MATCH_WITH);
2104 count = MAX_NUM_MATCH_WITH;
2107 if (1 < dlp->match_indices) {
2108 log_error("[%s] previous match_with ignored.", sec_name);
2109 dlp->match_indices = 1;
2110 } else if (1 > dlp->match_indices) {
2111 log_error("[%s] missing match_type, using \"%s\".",
2112 sec_name, tslp->match_types[0]);
2113 dlp->match_index[0] = 0;
2114 dlp->match_indices = 1;
2117 for (k = 0; k < count; k++) {
2118 for (j = 0; j < tslp->match_count; j++) {
2119 if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
2120 break;
2123 if (j >= tslp->match_count) {
2124 log_error("[%s] layer%d_match_with: invalid \"%s\".",
2125 sec_name, l, match_with[k]);
2126 } else if (1 < count) {
2127 int m;
2129 for (m = 0; m < dlp->match_indices; m++) {
2130 if (dlp->match_index[m] == j) {
2131 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
2132 sec_name, l, match_with[k]);
2133 break;
2136 if (m >= dlp->match_indices) {
2137 dlp->match_index[dlp->match_indices++] = j;
2139 } else {
2140 dlp->match_index[dlp->match_indices++] = j;
2143 free(match_with);
2144 match_with = NULL;
2147 /* Check match_indices */
2148 switch (dlp->match_indices) {
2149 case 0:
2150 case 1:
2151 dlp->match_style = MATCH_NONE;
2152 break;
2153 case 2:
2154 if (dlp->match_index[0] == dlp->match_index[1] ) {
2155 dlp->match_style = MATCH_SAME;
2156 } else {
2157 dlp->match_style = MATCH_PAIR;
2159 break;
2160 default:
2161 dlp->match_style = MATCH_FULL;
2162 break;
2165 sprite_type
2166 = secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
2167 sec_name, l);
2168 dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
2170 switch (dlp->sprite_type) {
2171 case CELL_WHOLE:
2172 /* OK, no problem */
2173 break;
2174 case CELL_CORNER:
2175 if (dlp->is_tall
2176 || dlp->offset_x > 0
2177 || dlp->offset_y > 0) {
2178 log_error("[%s] layer %d: you cannot have tall terrain or\n"
2179 "a sprite offset with a cell-based drawing method.",
2180 sec_name, l);
2181 dlp->is_tall = FALSE;
2182 dlp->offset_x = dlp->offset_y = 0;
2184 break;
2188 if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
2189 log_error("warning: multiple tile sections containing terrain tag \"%s\".",
2190 draw->name);
2191 goto ON_ERROR;
2193 } section_list_iterate_end;
2194 section_list_destroy(sections);
2195 sections = NULL;
2197 t->estyle_hash = estyle_hash_new();
2199 for (i = 0; i < ESTYLE_COUNT; i++) {
2200 t->style_lists[i] = extra_type_list_new();
2202 t->flagged_bases_list = extra_type_list_new();
2204 for (i = 0; (extraname = secfile_lookup_str_default(file, NULL,
2205 "extras.styles%d.name",
2206 i)); i++) {
2207 const char *style_name;
2208 enum extrastyle_id style;
2210 style_name = secfile_lookup_str_default(file, "Single1",
2211 "extras.styles%d.style", i);
2212 style = extrastyle_id_by_name(style_name, fc_strcasecmp);
2213 if (!extrastyle_id_is_valid(style)) {
2214 log_error("Unknown extra style \"%s\" for road \"%s\"",
2215 style_name, extraname);
2216 goto ON_ERROR;
2219 if (!estyle_hash_insert(t->estyle_hash, extraname, style)) {
2220 log_error("warning: duplicate extrastyle entry [%s].", extraname);
2221 goto ON_ERROR;
2225 spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
2226 "tilespec.files");
2227 if (NULL == spec_filenames || 0 == num_spec_files) {
2228 log_error("No tile graphics files specified in \"%s\"", fname);
2229 goto ON_ERROR;
2232 fc_assert(t->sprite_hash == NULL);
2233 t->sprite_hash = sprite_hash_new();
2234 for (i = 0; i < num_spec_files; i++) {
2235 struct specfile *sf = fc_malloc(sizeof(*sf));
2236 const char *dname;
2238 log_debug("spec file %s", spec_filenames[i]);
2240 sf->big_sprite = NULL;
2241 dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
2242 if (!dname) {
2243 if (verbose) {
2244 log_error("Can't find spec file \"%s\".", spec_filenames[i]);
2246 goto ON_ERROR;
2248 sf->file_name = fc_strdup(dname);
2249 scan_specfile(t, sf, duplicates_ok);
2251 specfile_list_prepend(t->specfiles, sf);
2253 free(spec_filenames);
2255 t->color_system = color_system_read(file);
2257 /* FIXME: remove this hack. */
2258 t->preferred_themes =
2259 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2260 "tilespec.preferred_themes");
2261 if (num_preferred_themes <= 0) {
2262 t->preferred_themes =
2263 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2264 "tilespec.prefered_themes");
2265 if (num_preferred_themes > 0) {
2266 log_deprecation("Entry tilespec.prefered_themes in tilespec."
2267 " Use correct spelling tilespec.preferred_themes instead");
2270 t->num_preferred_themes = num_preferred_themes;
2271 for (i = 0; i < t->num_preferred_themes; i++) {
2272 t->preferred_themes[i] = fc_strdup(t->preferred_themes[i]);
2275 secfile_check_unused(file);
2276 secfile_destroy(file);
2277 log_verbose("finished reading \"%s\".", fname);
2278 free(fname);
2280 return t;
2282 ON_ERROR:
2283 secfile_destroy(file);
2284 free(fname);
2285 tileset_free(t);
2286 if (NULL != sections) {
2287 section_list_destroy(sections);
2289 return NULL;
2292 /**********************************************************************
2293 Returns a text name for the citizen, as used in the tileset.
2294 ***********************************************************************/
2295 static const char *citizen_rule_name(enum citizen_category citizen)
2297 /* These strings are used in reading the tileset. Do not
2298 * translate. */
2299 switch (citizen) {
2300 case CITIZEN_HAPPY:
2301 return "happy";
2302 case CITIZEN_CONTENT:
2303 return "content";
2304 case CITIZEN_UNHAPPY:
2305 return "unhappy";
2306 case CITIZEN_ANGRY:
2307 return "angry";
2308 default:
2309 break;
2311 log_error("Unknown citizen type: %d.", (int) citizen);
2312 return NULL;
2315 /****************************************************************************
2316 Return a directional string for the cardinal directions. Normally the
2317 binary value 1000 will be converted into "n1e0s0w0". This is in a
2318 clockwise ordering.
2319 ****************************************************************************/
2320 static const char *cardinal_index_str(const struct tileset *t, int idx)
2322 static char c[64];
2323 int i;
2325 c[0] = '\0';
2326 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2327 int value = (idx >> i) & 1;
2329 cat_snprintf(c, sizeof(c), "%s%d",
2330 dir_get_tileset_name(t->cardinal_tileset_dirs[i]), value);
2333 return c;
2336 /****************************************************************************
2337 Do the same thing as cardinal_str, except including all valid directions.
2338 The returned string is a pointer to static memory.
2339 ****************************************************************************/
2340 static char *valid_index_str(const struct tileset *t, int idx)
2342 static char c[64];
2343 int i;
2345 c[0] = '\0';
2346 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2347 int value = (idx >> i) & 1;
2349 cat_snprintf(c, sizeof(c), "%s%d",
2350 dir_get_tileset_name(t->valid_tileset_dirs[i]), value);
2353 return c;
2356 /**************************************************************************
2357 Loads the sprite. If the sprite is already loaded a reference
2358 counter is increased. Can return NULL if the sprite couldn't be
2359 loaded.
2360 **************************************************************************/
2361 static struct sprite *load_sprite(struct tileset *t, const char *tag_name)
2363 struct small_sprite *ss;
2365 log_debug("load_sprite(tag='%s')", tag_name);
2366 /* Lookup information about where the sprite is found. */
2367 if (!sprite_hash_lookup(t->sprite_hash, tag_name, &ss)) {
2368 return NULL;
2371 fc_assert(ss->ref_count >= 0);
2373 if (!ss->sprite) {
2374 /* If the sprite hasn't been loaded already, then load it. */
2375 fc_assert(ss->ref_count == 0);
2376 if (ss->file) {
2377 ss->sprite = load_gfx_file(ss->file);
2378 if (!ss->sprite) {
2379 tileset_error(LOG_FATAL, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2380 ss->file, tag_name);
2382 } else {
2383 int sf_w, sf_h;
2385 ensure_big_sprite(ss->sf);
2386 get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2387 if (ss->x < 0 || ss->x + ss->width > sf_w
2388 || ss->y < 0 || ss->y + ss->height > sf_h) {
2389 tileset_error(LOG_ERROR, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2390 tag_name, ss->sf->file_name);
2391 return NULL;
2393 ss->sprite =
2394 crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height,
2395 NULL, -1, -1);
2399 /* Track the reference count so we know when to free the sprite. */
2400 ss->ref_count++;
2402 return ss->sprite;
2405 /**************************************************************************
2406 Create a sprite with the given color and tag.
2407 **************************************************************************/
2408 static struct sprite *create_plr_sprite(struct color *pcolor)
2410 struct sprite *sprite;
2412 fc_assert_ret_val(pcolor != NULL, NULL);
2414 sprite = create_sprite(128, 64, pcolor);
2416 return sprite;
2419 /**************************************************************************
2420 Unloads the sprite. Decrease the reference counter. If the last
2421 reference is removed the sprite is freed.
2422 **************************************************************************/
2423 static void unload_sprite(struct tileset *t, const char *tag_name)
2425 struct small_sprite *ss;
2427 sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
2428 fc_assert_ret(ss);
2429 fc_assert_ret(ss->ref_count >= 1);
2430 fc_assert_ret(ss->sprite);
2432 ss->ref_count--;
2434 if (ss->ref_count == 0) {
2435 /* Nobody's using the sprite anymore, so we should free it. We know
2436 * where to find it if we need it again. */
2437 log_debug("freeing sprite '%s'.", tag_name);
2438 free_sprite(ss->sprite);
2439 ss->sprite = NULL;
2443 /**************************************************************************
2444 Return TRUE iff the specified sprite exists in the tileset (whether
2445 or not it is currently loaded).
2446 **************************************************************************/
2447 static bool sprite_exists(const struct tileset *t, const char *tag_name)
2449 /* Lookup information about where the sprite is found. */
2450 return sprite_hash_lookup(t->sprite_hash, tag_name, NULL);
2453 /* Not very safe, but convenient: */
2454 #define SET_SPRITE(field, tag) \
2455 do { \
2456 t->sprites.field = load_sprite(t, tag); \
2457 if (t->sprites.field == NULL) { \
2458 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2460 } while(FALSE)
2462 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2463 #define SET_SPRITE_ALT(field, tag, alt) \
2464 do { \
2465 t->sprites.field = load_sprite(t, tag); \
2466 if (!t->sprites.field) { \
2467 t->sprites.field = load_sprite(t, alt); \
2469 if (t->sprites.field == NULL) { \
2470 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are " \
2471 "both missing."), tag, alt); \
2473 } while(FALSE)
2475 /* Sets sprites.field to tag, or NULL if not available */
2476 #define SET_SPRITE_OPT(field, tag) \
2477 t->sprites.field = load_sprite(t, tag)
2479 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2480 do { \
2481 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2482 "sprite", #field); \
2483 } while (FALSE)
2485 /****************************************************************************
2486 Setup the graphics for specialist types.
2487 ****************************************************************************/
2488 void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
2490 /* Load the specialist sprite graphics. */
2491 char buffer[512];
2492 int j;
2493 const char *name = specialist_rule_name(specialist_by_number(id));
2494 const char *graphic_alt = specialist_by_number(id)->graphic_alt;
2496 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2497 /* Try rule name + index number */
2498 fc_snprintf(buffer, sizeof(buffer), "specialist.%s_%d", name, j);
2499 t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer);
2501 /* Break if no more index specific sprites are defined */
2502 if (!t->sprites.specialist[id].sprite[j]) {
2503 break;
2507 /* Nothing? Try the alt tag */
2508 if (j == 0) {
2509 t->sprites.specialist[id].sprite[j] = load_sprite(t, graphic_alt);
2511 if (t->sprites.specialist[id].sprite[j]) {
2512 j = 1;
2516 t->sprites.specialist[id].count = j;
2518 /* Still nothing? Give up. */
2519 if (j == 0) {
2520 tileset_error(LOG_FATAL, _("No graphics for specialist \"%s\"."), name);
2524 /****************************************************************************
2525 Setup the graphics for (non-specialist) citizen types.
2526 ****************************************************************************/
2527 static void tileset_setup_citizen_types(struct tileset *t)
2529 int i, j;
2530 char buffer[512];
2532 /* Load the citizen sprite graphics, no specialist. */
2533 for (i = 0; i < CITIZEN_LAST; i++) {
2534 const char *name = citizen_rule_name(i);
2536 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2537 fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
2538 t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer);
2539 if (!t->sprites.citizen[i].sprite[j]) {
2540 break;
2543 t->sprites.citizen[i].count = j;
2544 if (j == 0) {
2545 tileset_error(LOG_FATAL, _("No graphics for citizen \"%s\"."), name);
2550 /****************************************************************************
2551 Return the sprite in the city_sprite listing that corresponds to this
2552 city - based on city style and size.
2554 See also load_city_sprite, free_city_sprite.
2555 ****************************************************************************/
2556 static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
2557 const struct city *pcity)
2559 /* get style and match the best tile based on city size */
2560 int style = style_of_city(pcity);
2561 int num_thresholds;
2562 struct city_style_threshold *thresholds;
2563 int img_index;
2565 fc_assert_ret_val(style < city_sprite->num_styles, NULL);
2567 num_thresholds = city_sprite->styles[style].land_num_thresholds;
2568 thresholds = city_sprite->styles[style].land_thresholds;
2570 if (num_thresholds == 0) {
2571 return NULL;
2574 /* Get the sprite with the index defined by the effects. */
2575 img_index = pcity->client.city_image;
2576 if (img_index == -100) {
2577 /* Server doesn't know right value as this is from old savegame.
2578 * Guess here based on *client* side information as was done in
2579 * versions where information was not saved to savegame - this should
2580 * give us right answer of what city looked like by the time it was
2581 * put under FoW. */
2582 img_index = get_city_bonus(pcity, EFT_CITY_IMAGE);
2584 img_index = CLIP(0, img_index, num_thresholds - 1);
2586 return thresholds[img_index].sprite;
2589 /****************************************************************************
2590 Allocates one threshold set for city sprite
2591 ****************************************************************************/
2592 static int load_city_thresholds_sprites(struct tileset *t, const char *tag,
2593 char *graphic, char *graphic_alt,
2594 struct city_style_threshold **thresholds)
2596 char buffer[128];
2597 char *gfx_in_use = graphic;
2598 int num_thresholds = 0;
2599 struct sprite *sprite;
2600 int size;
2602 *thresholds = NULL;
2604 for (size = 0; size < MAX_CITY_SIZE; size++) {
2605 fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
2606 gfx_in_use, tag, size);
2607 if ((sprite = load_sprite(t, buffer))) {
2608 num_thresholds++;
2609 *thresholds = fc_realloc(*thresholds, num_thresholds * sizeof(**thresholds));
2610 (*thresholds)[num_thresholds - 1].sprite = sprite;
2611 } else if (size == 0) {
2612 if (gfx_in_use == graphic) {
2613 /* Try again with graphic_alt. */
2614 size--;
2615 gfx_in_use = graphic_alt;
2616 } else {
2617 /* Don't load any others if the 0 element isn't there. */
2618 break;
2623 return num_thresholds;
2626 /****************************************************************************
2627 Allocates and loads a new city sprite from the given sprite tags.
2629 tag may be NULL.
2631 See also get_city_sprite, free_city_sprite.
2632 ****************************************************************************/
2633 static struct city_sprite *load_city_sprite(struct tileset *t,
2634 const char *tag)
2636 struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
2637 int style;
2639 /* Store number of styles we have allocated memory for.
2640 * game.control.styles_count might change if client disconnects from
2641 * server and connects new one. */
2642 city_sprite->num_styles = game.control.styles_count;
2643 city_sprite->styles = fc_malloc(city_sprite->num_styles
2644 * sizeof(*city_sprite->styles));
2646 for (style = 0; style < city_sprite->num_styles; style++) {
2647 city_sprite->styles[style].land_num_thresholds =
2648 load_city_thresholds_sprites(t, tag, city_styles[style].graphic,
2649 city_styles[style].graphic_alt,
2650 &city_sprite->styles[style].land_thresholds);
2653 return city_sprite;
2656 /****************************************************************************
2657 Frees a city sprite.
2659 See also get_city_sprite, load_city_sprite.
2660 ****************************************************************************/
2661 static void free_city_sprite(struct city_sprite *city_sprite)
2663 int style;
2665 if (!city_sprite) {
2666 return;
2668 for (style = 0; style < city_sprite->num_styles; style++) {
2669 if (city_sprite->styles[style].land_thresholds) {
2670 free(city_sprite->styles[style].land_thresholds);
2673 free(city_sprite->styles);
2674 free(city_sprite);
2677 /**********************************************************************
2678 Initialize 'sprites' structure based on hardwired tags which
2679 freeciv always requires.
2680 ***********************************************************************/
2681 static void tileset_lookup_sprite_tags(struct tileset *t)
2683 char buffer[512], buffer2[512];
2684 const int W = t->normal_tile_width, H = t->normal_tile_height;
2685 int i, j, f;
2687 fc_assert_ret(t->sprite_hash != NULL);
2689 SET_SPRITE(treaty_thumb[0], "treaty.disagree_thumb_down");
2690 SET_SPRITE(treaty_thumb[1], "treaty.agree_thumb_up");
2692 for (j = 0; j < INDICATOR_COUNT; j++) {
2693 const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2695 for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2696 fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
2697 SET_SPRITE(indicator[j][i], buffer);
2701 SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
2702 SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
2703 SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
2704 if (t->type == TS_ISOMETRIC) {
2705 SET_SPRITE(dither_tile, "t.dither_tile");
2708 SET_SPRITE(mask.tile, "mask.tile");
2709 SET_SPRITE(mask.worked_tile, "mask.worked_tile");
2710 SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
2712 SET_SPRITE(tax_luxury, "s.tax_luxury");
2713 SET_SPRITE(tax_science, "s.tax_science");
2714 SET_SPRITE(tax_gold, "s.tax_gold");
2716 tileset_setup_citizen_types(t);
2718 for (i = 0; i < SPACESHIP_COUNT; i++) {
2719 const char *names[SPACESHIP_COUNT]
2720 = {"solar_panels", "life_support", "habitation",
2721 "structural", "fuel", "propulsion", "exhaust"};
2723 fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
2724 SET_SPRITE(spaceship[i], buffer);
2727 for (i = 0; i < CURSOR_LAST; i++) {
2728 for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2729 const char *names[CURSOR_LAST] =
2730 {"goto", "patrol", "paradrop", "nuke", "select",
2731 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2732 struct small_sprite *ss;
2734 fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2735 fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
2736 SET_SPRITE(cursor[i].frame[f], buffer);
2737 if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
2738 t->sprites.cursor[i].hot_x = ss->hot_x;
2739 t->sprites.cursor[i].hot_y = ss->hot_y;
2744 for (i = 0; i < ICON_COUNT; i++) {
2745 const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
2747 fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
2748 SET_SPRITE(icon[i], buffer);
2751 for (i = 0; i < E_COUNT; i++) {
2752 const char *tag = get_event_tag(i);
2754 SET_SPRITE(events[i], tag);
2757 SET_SPRITE(explode.nuke, "explode.nuke");
2759 sprite_vector_init(&t->sprites.explode.unit);
2760 for (i = 0; ; i++) {
2761 struct sprite *sprite;
2763 fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
2764 sprite = load_sprite(t, buffer);
2765 if (!sprite) {
2766 break;
2768 sprite_vector_append(&t->sprites.explode.unit, sprite);
2771 SET_SPRITE(unit.auto_attack, "unit.auto_attack");
2772 SET_SPRITE(unit.auto_settler, "unit.auto_settler");
2773 SET_SPRITE(unit.auto_explore, "unit.auto_explore");
2774 SET_SPRITE(unit.fortified, "unit.fortified");
2775 SET_SPRITE(unit.fortifying, "unit.fortifying");
2776 SET_SPRITE(unit.go_to, "unit.goto");
2777 SET_SPRITE(unit.irrigate, "unit.irrigate");
2778 SET_SPRITE(unit.plant, "unit.plant");
2779 SET_SPRITE(unit.pillage, "unit.pillage");
2780 SET_SPRITE(unit.sentry, "unit.sentry");
2781 SET_SPRITE(unit.convert, "unit.convert");
2782 SET_SPRITE(unit.stack, "unit.stack");
2783 SET_SPRITE(unit.loaded, "unit.loaded");
2784 SET_SPRITE(unit.transform, "unit.transform");
2785 SET_SPRITE(unit.connect, "unit.connect");
2786 SET_SPRITE(unit.patrol, "unit.patrol");
2787 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
2788 fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
2789 fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
2790 fc_assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
2791 SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
2793 SET_SPRITE(unit.lowfuel, "unit.lowfuel");
2794 SET_SPRITE(unit.tired, "unit.tired");
2796 for(i=0; i<NUM_TILES_HP_BAR; i++) {
2797 fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
2798 SET_SPRITE(unit.hp_bar[i], buffer);
2801 for (i = 0; i < MAX_VET_LEVELS; i++) {
2802 /* Veteran level sprites are optional. For instance "green" units
2803 * usually have no special graphic. */
2804 fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
2805 t->sprites.unit.vet_lev[i] = load_sprite(t, buffer);
2808 t->sprites.unit.select[0] = NULL;
2809 if (sprite_exists(t, "unit.select0")) {
2810 for (i = 0; i < NUM_TILES_SELECT; i++) {
2811 fc_snprintf(buffer, sizeof(buffer), "unit.select%d", i);
2812 SET_SPRITE(unit.select[i], buffer);
2816 SET_SPRITE(citybar.shields, "citybar.shields");
2817 SET_SPRITE(citybar.food, "citybar.food");
2818 SET_SPRITE(citybar.trade, "citybar.trade");
2819 SET_SPRITE(citybar.occupied, "citybar.occupied");
2820 SET_SPRITE(citybar.background, "citybar.background");
2821 sprite_vector_init(&t->sprites.citybar.occupancy);
2822 for (i = 0; ; i++) {
2823 struct sprite *sprite;
2825 fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
2826 sprite = load_sprite(t, buffer);
2827 if (!sprite) {
2828 break;
2830 sprite_vector_append(&t->sprites.citybar.occupancy, sprite);
2832 if (t->sprites.citybar.occupancy.size < 2) {
2833 tileset_error(LOG_FATAL, _("Missing necessary citybar.occupancy_N sprites."));
2836 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2837 SET_EDITOR_SPRITE(erase);
2838 SET_EDITOR_SPRITE(brush);
2839 SET_EDITOR_SPRITE(copy);
2840 SET_EDITOR_SPRITE(paste);
2841 SET_EDITOR_SPRITE(copypaste);
2842 SET_EDITOR_SPRITE(startpos);
2843 SET_EDITOR_SPRITE(terrain);
2844 SET_EDITOR_SPRITE(terrain_resource);
2845 SET_EDITOR_SPRITE(terrain_special);
2846 SET_EDITOR_SPRITE(unit);
2847 SET_EDITOR_SPRITE(city);
2848 SET_EDITOR_SPRITE(vision);
2849 SET_EDITOR_SPRITE(territory);
2850 SET_EDITOR_SPRITE(properties);
2851 SET_EDITOR_SPRITE(road);
2852 SET_EDITOR_SPRITE(military_base);
2853 #undef SET_EDITOR_SPRITE
2855 SET_SPRITE(city.disorder, "city.disorder");
2857 /* Fallbacks for goto path turn numbers:
2858 * path.step_%d, path.exhausted_mp_%d
2859 * --> path.turns_%d
2860 * --> city.size_%d */
2861 #define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name) \
2862 fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
2863 SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer); \
2864 if (t->sprites.path.s[state].turns ## factor_name [i] == NULL) { \
2865 t->sprites.path.s[state].turns ## factor_name [i] = \
2866 t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i]; \
2868 for(i=0; i<NUM_TILES_DIGITS; i++) {
2869 fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
2870 SET_SPRITE(city.size[i], buffer);
2871 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
2872 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns[i], buffer2, buffer);
2873 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step",,);
2874 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp",,);
2876 fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
2877 SET_SPRITE(city.size_tens[i], buffer);
2878 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
2879 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns_tens[i], buffer2, buffer);
2880 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 0, _tens);
2881 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 0, _tens);
2883 fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
2884 SET_SPRITE_OPT(city.size_hundreds[i], buffer);
2885 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
2886 SET_SPRITE_ALT_OPT(path.s[GTS_MP_LEFT].turns_hundreds[i], buffer2,
2887 buffer);
2888 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 00, _hundreds);
2889 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 00, _hundreds);
2891 fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
2892 SET_SPRITE(city.tile_foodnum[i], buffer);
2893 fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
2894 SET_SPRITE(city.tile_shieldnum[i], buffer);
2895 fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
2896 SET_SPRITE(city.tile_tradenum[i], buffer);
2898 #undef SET_GOTO_TURN_SPRITE
2900 /* Must have at least one upkeep sprite per output type (and unhappy) */
2901 /* The rest are optional; we copy the previous sprite for unspecified ones */
2902 fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
2903 SET_SPRITE(upkeep.unhappy[0], buffer);
2904 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
2905 fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
2906 if (sprite_exists(t, buffer2)) {
2907 SET_SPRITE(upkeep.unhappy[i], buffer2);
2908 fc_strlcpy(buffer, buffer2, sizeof(buffer));
2909 } else {
2910 SET_SPRITE(upkeep.unhappy[i], buffer);
2913 output_type_iterate(o) {
2914 fc_snprintf(buffer, sizeof(buffer),
2915 "upkeep.%s", get_output_identifier(o));
2916 SET_SPRITE_OPT(upkeep.output[o][0], buffer);
2917 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
2918 fc_snprintf(buffer2, sizeof(buffer2),
2919 "upkeep.%s%d", get_output_identifier(o), i+1);
2920 if (sprite_exists(t, buffer2)) {
2921 SET_SPRITE(upkeep.output[o][i], buffer2);
2922 fc_strlcpy(buffer, buffer2, sizeof(buffer));
2923 } else {
2924 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
2925 SET_SPRITE_OPT(upkeep.output[o][i], buffer);
2928 } output_type_iterate_end;
2930 t->max_upkeep_height = calculate_max_upkeep_height(t);
2932 SET_SPRITE(user.attention, "user.attention");
2934 SET_SPRITE_OPT(path.s[GTS_MP_LEFT].specific, "path.normal");
2935 SET_SPRITE_OPT(path.s[GTS_EXHAUSTED_MP].specific, "path.exhausted_mp");
2936 SET_SPRITE_OPT(path.s[GTS_TURN_STEP].specific, "path.step");
2937 SET_SPRITE(path.waypoint, "path.waypoint");
2939 SET_SPRITE(tx.fog, "tx.fog");
2941 sprite_vector_init(&t->sprites.colors.overlays);
2942 for (i = 0; ; i++) {
2943 struct sprite *sprite;
2945 fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
2946 sprite = load_sprite(t, buffer);
2947 if (!sprite) {
2948 break;
2950 sprite_vector_append(&t->sprites.colors.overlays, sprite);
2952 if (i == 0) {
2953 tileset_error(LOG_FATAL, _("Missing overlay-color sprite colors.overlay_0."));
2956 /* Chop up and build the overlay graphics. */
2957 sprite_vector_reserve(&t->sprites.city.worked_tile_overlay,
2958 sprite_vector_size(&t->sprites.colors.overlays));
2959 sprite_vector_reserve(&t->sprites.city.unworked_tile_overlay,
2960 sprite_vector_size(&t->sprites.colors.overlays));
2961 for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
2962 struct sprite *color, *color_mask;
2963 struct sprite *worked, *unworked;
2965 color = *sprite_vector_get(&t->sprites.colors.overlays, i);
2966 color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0);
2967 worked = crop_sprite(color_mask, 0, 0, W, H,
2968 t->sprites.mask.worked_tile, 0, 0);
2969 unworked = crop_sprite(color_mask, 0, 0, W, H,
2970 t->sprites.mask.unworked_tile, 0, 0);
2971 free_sprite(color_mask);
2972 t->sprites.city.worked_tile_overlay.p[i] = worked;
2973 t->sprites.city.unworked_tile_overlay.p[i] = unworked;
2978 SET_SPRITE(grid.unavailable, "grid.unavailable");
2979 SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
2981 for (i = 0; i < EDGE_COUNT; i++) {
2982 int be;
2984 if (i == EDGE_UD && t->hex_width == 0) {
2985 continue;
2986 } else if (i == EDGE_LR && t->hex_height == 0) {
2987 continue;
2990 fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
2991 SET_SPRITE(grid.main[i], buffer);
2993 fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
2994 SET_SPRITE(grid.city[i], buffer);
2996 fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
2997 SET_SPRITE(grid.worked[i], buffer);
2999 fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
3000 SET_SPRITE(grid.selected[i], buffer);
3002 fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
3003 SET_SPRITE(grid.coastline[i], buffer);
3005 for (be = 0; be < 2; be++) {
3006 fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
3007 edge_name[i][be]);
3008 SET_SPRITE(grid.borders[i][be], buffer);
3013 switch (t->darkness_style) {
3014 case DARKNESS_NONE:
3015 /* Nothing. */
3016 break;
3017 case DARKNESS_ISORECT:
3019 /* Isometric: take a single tx.darkness tile and split it into 4. */
3020 struct sprite *darkness = load_sprite(t, "tx.darkness");
3021 const int ntw = t->normal_tile_width, nth = t->normal_tile_height;
3022 int offsets[4][2] = {{ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
3024 if (!darkness) {
3025 tileset_error(LOG_FATAL, _("Sprite tx.darkness missing."));
3027 for (i = 0; i < 4; i++) {
3028 t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
3029 offsets[i][1], ntw / 2, nth / 2,
3030 NULL, 0, 0);
3033 break;
3034 case DARKNESS_CARD_SINGLE:
3035 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3036 enum direction8 dir = t->cardinal_tileset_dirs[i];
3038 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3039 dir_get_tileset_name(dir));
3040 SET_SPRITE(tx.darkness[i], buffer);
3042 break;
3043 case DARKNESS_CARD_FULL:
3044 for(i = 1; i < t->num_index_cardinal; i++) {
3045 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3046 cardinal_index_str(t, i));
3047 SET_SPRITE(tx.darkness[i], buffer);
3049 break;
3050 case DARKNESS_CORNER:
3051 t->sprites.tx.fullfog = fc_realloc(t->sprites.tx.fullfog,
3052 81 * sizeof(*t->sprites.tx.fullfog));
3053 for (i = 0; i < 81; i++) {
3054 /* Unknown, fog, known. */
3055 char ids[] = {'u', 'f', 'k'};
3056 char buf[512] = "t.fog";
3057 int values[4], vi, k = i;
3059 for (vi = 0; vi < 4; vi++) {
3060 values[vi] = k % 3;
3061 k /= 3;
3063 cat_snprintf(buf, sizeof(buf), "_%c", ids[values[vi]]);
3065 fc_assert(k == 0);
3067 t->sprites.tx.fullfog[i] = load_sprite(t, buf);
3069 break;
3072 /* no other place to initialize these variables */
3073 sprite_vector_init(&t->sprites.nation_flag);
3074 sprite_vector_init(&t->sprites.nation_shield);
3077 /**************************************************************************
3078 Load sprites of one river type.
3079 **************************************************************************/
3080 static bool load_river_sprites(struct tileset *t,
3081 struct river_sprites *store, const char *tag_pfx)
3083 int i;
3084 char buffer[512];
3086 for (i = 0; i < t->num_index_cardinal; i++) {
3087 fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
3088 tag_pfx, cardinal_index_str(t, i));
3089 store->spec[i] = load_sprite(t, buffer);
3090 if (store->spec[i] == NULL) {
3091 return FALSE;
3095 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3096 fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%s",
3097 tag_pfx, dir_get_tileset_name(t->cardinal_tileset_dirs[i]));
3098 store->outlet[i] = load_sprite(t, buffer);
3099 if (store->outlet[i] == NULL) {
3100 if (t->cardinal_tileset_dirs[i] == DIR8_NORTHWEST
3101 || t->cardinal_tileset_dirs[i] == DIR8_NORTHEAST
3102 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHEAST
3103 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHWEST) {
3104 log_debug("Missing \"%s\", support for this is deprecated.", buffer);
3105 } else {
3106 return FALSE;
3111 return TRUE;
3114 /**************************************************************************
3115 Frees any internal buffers which are created by load_sprite. Should
3116 be called after the last (for a given period of time) load_sprite
3117 call. This saves a fair amount of memory, but it will take extra time
3118 the next time we start loading sprites again.
3119 **************************************************************************/
3120 void finish_loading_sprites(struct tileset *t)
3122 specfile_list_iterate(t->specfiles, sf) {
3123 if (sf->big_sprite) {
3124 free_sprite(sf->big_sprite);
3125 sf->big_sprite = NULL;
3127 } specfile_list_iterate_end;
3130 /**********************************************************************
3131 Load the tiles; requires tilespec_read_toplevel() called previously.
3132 Leads to tile_sprites being allocated and filled with pointers
3133 to sprites. Also sets up and populates sprite_hash, and calls func
3134 to initialize 'sprites' structure.
3135 ***********************************************************************/
3136 void tileset_load_tiles(struct tileset *t)
3138 tileset_lookup_sprite_tags(t);
3139 finish_loading_sprites(t);
3142 /**********************************************************************
3143 Lookup sprite to match tag, or else to match alt if don't find,
3144 or else return NULL, and emit log message.
3145 ***********************************************************************/
3146 struct sprite *tiles_lookup_sprite_tag_alt(struct tileset *t,
3147 enum log_level level,
3148 const char *tag, const char *alt,
3149 const char *what,
3150 const char *name)
3152 struct sprite *sp;
3154 /* (should get sprite_hash before connection) */
3155 fc_assert_ret_val_msg(NULL != t->sprite_hash, NULL,
3156 "attempt to lookup for %s \"%s\" before "
3157 "sprite_hash setup", what, name);
3159 sp = load_sprite(t, tag);
3160 if (sp) return sp;
3162 sp = load_sprite(t, alt);
3163 if (sp) {
3164 log_verbose("Using alternate graphic \"%s\" "
3165 "(instead of \"%s\") for %s \"%s\".",
3166 alt, tag, what, name);
3167 return sp;
3170 tileset_error(level, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3171 tag, alt, what, name);
3173 return NULL;
3176 /**********************************************************************
3177 Helper function to load sprite for one unit orientation
3178 ***********************************************************************/
3179 static bool tileset_setup_unit_direction(struct tileset *t,
3180 int uidx,
3181 const char *base_str,
3182 enum direction8 dir,
3183 const char *dirsuffix)
3185 char buf[2048];
3187 fc_snprintf(buf, sizeof(buf), "%s_%s", base_str, dirsuffix);
3189 /* We don't use _alt graphics here, as that could lead to loading
3190 * real icon gfx, but alternative orientation gfx. Tileset author
3191 * probably meant icon gfx to be used as fallback for all orientations */
3192 t->sprites.units.facing[uidx][dir] = load_sprite(t, buf);
3194 if (t->sprites.units.facing[uidx][dir] != NULL) {
3195 return TRUE;
3198 return FALSE;
3201 /**********************************************************************
3202 Try to setup all unit type sprites from single tag
3203 ***********************************************************************/
3204 bool static tileset_setup_unit_type_from_tag(struct tileset *t,
3205 int uidx, const char *tag)
3207 bool facing_sprites = TRUE;
3209 t->sprites.units.icon[uidx] = load_sprite(t, tag);
3211 #define LOAD_FACING_SPRITE(dir, dname) \
3212 if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
3213 facing_sprites = FALSE; \
3216 LOAD_FACING_SPRITE(DIR8_NORTHWEST, "nw");
3217 LOAD_FACING_SPRITE(DIR8_NORTH, "n");
3218 LOAD_FACING_SPRITE(DIR8_NORTHEAST, "ne");
3219 LOAD_FACING_SPRITE(DIR8_WEST, "w");
3220 LOAD_FACING_SPRITE(DIR8_EAST, "e");
3221 LOAD_FACING_SPRITE(DIR8_SOUTHWEST, "sw");
3222 LOAD_FACING_SPRITE(DIR8_SOUTH, "s");
3223 LOAD_FACING_SPRITE(DIR8_SOUTHEAST, "se");
3225 if (!facing_sprites && t->sprites.units.icon[uidx] == NULL) {
3226 /* Neither icon gfx or orientation sprites */
3227 return FALSE;
3230 /* Fix a random orientation for displaying unit type in help etc.
3231 * We don't necessarily know the map topology yet, so choose a seed
3232 * that can be used to pick a valid direction later (24 is lcm(6,8)).
3233 * See get_unittype_sprite(). */
3234 t->sprites.units.default_dir_seed[uidx] = fc_rand(24);
3236 return TRUE;
3238 #undef LOAD_FACING_SPRITE
3241 /**********************************************************************
3242 Set unit_type sprite value; should only happen after
3243 tilespec_load_tiles().
3244 ***********************************************************************/
3245 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
3247 int uidx = utype_index(ut);
3249 if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
3250 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
3251 tileset_error(LOG_FATAL, _("Missing %s unit sprite for tags \"%s\" and alternative \"%s\"."),
3252 utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
3256 /**********************************************************************
3257 Set improvement_type sprite value; should only happen after
3258 tilespec_load_tiles().
3259 ***********************************************************************/
3260 void tileset_setup_impr_type(struct tileset *t,
3261 struct impr_type *pimprove)
3263 t->sprites.building[improvement_index(pimprove)] =
3264 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, pimprove->graphic_str,
3265 pimprove->graphic_alt, "improvement",
3266 improvement_rule_name(pimprove));
3268 /* should maybe do something if NULL, eg generic default? */
3271 /**********************************************************************
3272 Set tech_type sprite value; should only happen after
3273 tilespec_load_tiles().
3274 ***********************************************************************/
3275 void tileset_setup_tech_type(struct tileset *t,
3276 struct advance *padvance)
3278 if (valid_advance(padvance)) {
3279 t->sprites.tech[advance_index(padvance)] =
3280 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, padvance->graphic_str,
3281 padvance->graphic_alt, "technology",
3282 advance_rule_name(padvance));
3284 /* should maybe do something if NULL, eg generic default? */
3285 } else {
3286 t->sprites.tech[advance_index(padvance)] = NULL;
3290 /****************************************************************************
3291 Set resource sprite values; should only happen after
3292 tilespec_load_tiles().
3293 ****************************************************************************/
3294 void tileset_setup_resource(struct tileset *t,
3295 const struct resource *presource)
3297 fc_assert_ret(NULL != presource);
3298 t->sprites.resource[resource_index(presource)] =
3299 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, presource->graphic_str,
3300 presource->graphic_alt, "resource",
3301 resource_rule_name(presource));
3304 /****************************************************************************
3305 Set extra sprite values; should only happen after
3306 tilespec_load_tiles().
3307 ****************************************************************************/
3308 void tileset_setup_extra(struct tileset *t,
3309 struct extra_type *pextra)
3311 const int id = extra_index(pextra);
3312 enum extrastyle_id extrastyle;
3314 if (!fc_strcasecmp(pextra->graphic_str, "none")) {
3315 /* Extra without graphics */
3316 t->sprites.extras[id].extrastyle = extrastyle_id_invalid();
3317 } else {
3319 if (!estyle_hash_lookup(t->estyle_hash, pextra->graphic_str,
3320 &extrastyle)
3321 && !estyle_hash_lookup(t->estyle_hash, pextra->graphic_alt,
3322 &extrastyle)) {
3323 tileset_error(LOG_FATAL, _("No extrastyle for \"%s\" or \"%s\"."),
3324 pextra->graphic_str,
3325 pextra->graphic_alt);
3328 t->sprites.extras[id].extrastyle = extrastyle;
3330 extra_type_list_append(t->style_lists[extrastyle], pextra);
3332 if (extra_has_flag(pextra, EF_SHOW_FLAG)) {
3333 extra_type_list_append(t->flagged_bases_list, pextra);
3336 switch (extrastyle) {
3337 case ESTYLE_3LAYER:
3338 tileset_setup_base(t, pextra);
3339 break;
3341 case ESTYLE_ROAD_ALL_SEPARATE:
3342 case ESTYLE_ROAD_PARITY_COMBINED:
3343 case ESTYLE_ROAD_ALL_COMBINED:
3344 case ESTYLE_RIVER:
3345 tileset_setup_road(t, pextra);
3346 break;
3348 case ESTYLE_SINGLE1:
3349 case ESTYLE_SINGLE2:
3350 SET_SPRITE_ALT(extras[id].u.single, pextra->graphic_str, pextra->graphic_alt);
3351 break;
3353 case ESTYLE_CARDINALS:
3355 int i;
3356 char buffer[512];
3358 /* We use direction-specific irrigation and farmland graphics, if they
3359 * are available. If not, we just fall back to the basic irrigation
3360 * graphics. */
3361 for (i = 0; i < t->num_index_cardinal; i++) {
3362 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3363 pextra->graphic_str, cardinal_index_str(t, i));
3364 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer);
3365 if (!t->sprites.extras[id].u.cardinals[i]) {
3366 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, pextra->graphic_str);
3368 if (!t->sprites.extras[id].u.cardinals[i]) {
3369 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3370 pextra->graphic_alt, cardinal_index_str(t, i));
3371 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer);
3373 if (!t->sprites.extras[id].u.cardinals[i]) {
3374 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, pextra->graphic_alt);
3376 if (!t->sprites.extras[id].u.cardinals[i]) {
3377 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are "
3378 "both missing."),
3379 pextra->graphic_str, pextra->graphic_alt);
3383 break;
3384 case ESTYLE_COUNT:
3385 break;
3389 if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
3390 t->sprites.extras[id].activity = NULL;
3391 } else {
3392 t->sprites.extras[id].activity = load_sprite(t, pextra->activity_gfx);
3393 if (t->sprites.extras[id].activity == NULL) {
3394 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt);
3396 if (t->sprites.extras[id].activity == NULL) {
3397 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt2);
3399 if (t->sprites.extras[id].activity == NULL) {
3400 tileset_error(LOG_FATAL, _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
3401 extra_rule_name(pextra), pextra->activity_gfx,
3402 pextra->act_gfx_alt, pextra->act_gfx_alt2);
3406 if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
3407 t->sprites.extras[id].rmact = NULL;
3408 } else {
3409 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx);
3410 if (t->sprites.extras[id].rmact == NULL) {
3411 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx_alt);
3412 if (t->sprites.extras[id].rmact == NULL) {
3413 tileset_error(LOG_FATAL, _("Missing %s removal activity sprite for tags \"%s\" and alternative \"%s\"."),
3414 extra_rule_name(pextra), pextra->rmact_gfx, pextra->rmact_gfx_alt);
3420 /****************************************************************************
3421 Set road sprite values; should only happen after
3422 tilespec_load_tiles().
3423 ****************************************************************************/
3424 static void tileset_setup_road(struct tileset *t,
3425 struct extra_type *pextra)
3427 char full_tag_name[MAX_LEN_NAME + strlen("_isolated")];
3428 char full_alt_name[MAX_LEN_NAME + strlen("_isolated")];
3429 const int id = extra_index(pextra);
3430 int i;
3431 enum extrastyle_id extrastyle = t->sprites.extras[id].extrastyle;
3433 /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3434 ESTYLE_ROAD_PARITY_COMBINED. */
3435 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3436 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3437 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3438 "%s_isolated", pextra->graphic_str);
3439 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3440 "%s_isolated", pextra->graphic_alt);
3442 SET_SPRITE_ALT(extras[id].u.road.isolated, full_tag_name, full_alt_name);
3445 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
3446 /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each road type:
3447 * one going off in each direction. */
3448 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3449 enum direction8 dir = t->valid_tileset_dirs[i];
3450 const char *dir_name = dir_get_tileset_name(dir);
3452 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3453 "%s_%s", pextra->graphic_str, dir_name);
3454 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3455 "%s_%s", pextra->graphic_alt, dir_name);
3457 SET_SPRITE_ALT(extras[id].u.road.ru.dir[i], full_tag_name, full_alt_name);
3459 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3460 int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
3462 /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road type:
3463 * 16 each for cardinal and diagonal directions. Each set
3464 * of 16 provides a NSEW-indexed sprite to provide connectors for
3465 * all rails in the cardinal/diagonal directions. The 0 entry is
3466 * unused (the "isolated" sprite is used instead). */
3468 for (i = 1; i < num_index; i++) {
3469 char c[64] = "", d[64] = "";
3471 for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
3472 int value = (i >> j) & 1;
3474 cat_snprintf(c, sizeof(c), "%s%d",
3475 dir_get_tileset_name(t->valid_tileset_dirs[2 * j]),
3476 value);
3477 cat_snprintf(d, sizeof(d), "%s%d",
3478 dir_get_tileset_name(t->valid_tileset_dirs[2 * j + 1]),
3479 value);
3482 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3483 "%s_c_%s", pextra->graphic_str, c);
3484 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3485 "%s_c_%s", pextra->graphic_alt, c);
3487 SET_SPRITE_ALT(extras[id].u.road.ru.combo.even[i], full_tag_name, full_alt_name);
3489 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3490 "%s_d_%s", pextra->graphic_str, d);
3491 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3492 "%s_d_%s", pextra->graphic_alt, d);
3494 SET_SPRITE_ALT(extras[id].u.road.ru.combo.odd[i], full_tag_name, full_alt_name);
3496 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
3497 /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
3498 * Just go around clockwise, with all combinations. */
3499 for (i = 0; i < t->num_index_valid; i++) {
3500 char *idx_str = valid_index_str(t, i);
3502 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3503 "%s_%s", pextra->graphic_str, idx_str);
3504 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3505 "%s_%s", pextra->graphic_alt, idx_str);
3507 SET_SPRITE_ALT(extras[id].u.road.ru.total[i], full_tag_name, full_alt_name);
3509 } else if (extrastyle == ESTYLE_RIVER) {
3510 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3511 pextra->graphic_str)) {
3512 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3513 pextra->graphic_alt)) {
3514 tileset_error(LOG_FATAL, _("Cannot load river \"%s\" or \"%s\""),
3515 pextra->graphic_str, pextra->graphic_alt);
3518 } else {
3519 fc_assert(FALSE);
3522 /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3523 * ESTYLE_ROAD_PARITY_COMBINED. */
3524 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3525 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3526 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3527 enum direction8 dir = t->valid_tileset_dirs[i];
3529 if (!is_cardinal_tileset_dir(t, dir)) {
3530 const char *dtn = dir_get_tileset_name(dir);
3532 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3533 "%s_c_%s", pextra->graphic_str, dtn);
3534 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3535 "%s_c_%s", pextra->graphic_alt, dtn);
3537 SET_SPRITE_ALT_OPT(extras[id].u.road.corner[dir], full_tag_name, full_alt_name);
3543 /****************************************************************************
3544 Set base sprite values; should only happen after
3545 tilespec_load_tiles().
3546 ****************************************************************************/
3547 static void tileset_setup_base(struct tileset *t,
3548 const struct extra_type *pextra)
3550 char full_tag_name[MAX_LEN_NAME + strlen("_fg")];
3551 const int id = extra_index(pextra);
3553 fc_assert_ret(id >= 0 && id < extra_count());
3555 sz_strlcpy(full_tag_name, pextra->graphic_str);
3556 strcat(full_tag_name, "_bg");
3557 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name);
3559 sz_strlcpy(full_tag_name, pextra->graphic_str);
3560 strcat(full_tag_name, "_mg");
3561 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name);
3563 sz_strlcpy(full_tag_name, pextra->graphic_str);
3564 strcat(full_tag_name, "_fg");
3565 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name);
3567 if (t->sprites.extras[id].u.bmf.background == NULL
3568 && t->sprites.extras[id].u.bmf.middleground == NULL
3569 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3570 /* No primary graphics at all. Try alternative */
3571 log_verbose("Using alternate graphic \"%s\" "
3572 "(instead of \"%s\") for extra \"%s\".",
3573 pextra->graphic_alt, pextra->graphic_str,
3574 extra_rule_name(pextra));
3576 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3577 strcat(full_tag_name, "_bg");
3578 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name);
3580 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3581 strcat(full_tag_name, "_mg");
3582 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name);
3584 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3585 strcat(full_tag_name, "_fg");
3586 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name);
3588 if (t->sprites.extras[id].u.bmf.background == NULL
3589 && t->sprites.extras[id].u.bmf.middleground == NULL
3590 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3591 /* Cannot find alternative graphics either */
3592 tileset_error(LOG_FATAL, _("No graphics for extra \"%s\" at all!"),
3593 extra_rule_name(pextra));
3598 /**********************************************************************
3599 Set tile_type sprite values; should only happen after
3600 tilespec_load_tiles().
3601 ***********************************************************************/
3602 void tileset_setup_tile_type(struct tileset *t,
3603 const struct terrain *pterrain)
3605 struct drawing_data *draw;
3606 struct sprite *sprite;
3607 char buffer[MAX_LEN_NAME + 20];
3608 int i, l;
3610 if (0 == strlen(terrain_rule_name(pterrain))) {
3611 return;
3614 if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
3615 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
3616 tileset_error(LOG_FATAL, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3617 terrain_rule_name(pterrain), pterrain->graphic_str,
3618 pterrain->graphic_alt);
3621 if (draw->init) {
3622 t->sprites.drawing[terrain_index(pterrain)] = draw;
3623 return;
3626 /* Set up each layer of the drawing. */
3627 for (l = 0; l < draw->num_layers; l++) {
3628 struct drawing_layer *dlp = &draw->layer[l];
3629 struct tileset_layer *tslp = &t->layers[l];
3630 sprite_vector_init(&dlp->base);
3631 sprite_vector_init(&dlp->allocated);
3633 switch (dlp->sprite_type) {
3634 case CELL_WHOLE:
3635 switch (dlp->match_style) {
3636 case MATCH_NONE:
3637 /* Load whole sprites for this tile. */
3638 for (i = 0; ; i++) {
3639 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
3640 l, draw->name, i + 1);
3641 sprite = load_sprite(t, buffer);
3642 if (!sprite) {
3643 break;
3645 sprite_vector_reserve(&dlp->base, i + 1);
3646 dlp->base.p[i] = sprite;
3648 /* check for base sprite, allowing missing sprites above base */
3649 if (0 == i && 0 == l) {
3650 /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
3651 tileset_error(LOG_FATAL, _("Missing base sprite for tag \"%s\"."), buffer);
3653 break;
3654 case MATCH_SAME:
3655 /* Load 16 cardinally-matched sprites. */
3656 for (i = 0; i < t->num_index_cardinal; i++) {
3657 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
3658 l, draw->name, cardinal_index_str(t, i));
3659 dlp->match[i] =
3660 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3661 "matched terrain",
3662 terrain_rule_name(pterrain));
3664 break;
3665 case MATCH_PAIR:
3666 case MATCH_FULL:
3667 fc_assert(FALSE); /* not yet defined */
3668 break;
3670 break;
3671 case CELL_CORNER:
3673 const int count = dlp->match_indices;
3674 int number = NUM_CORNER_DIRS;
3676 switch (dlp->match_style) {
3677 case MATCH_NONE:
3678 /* do nothing */
3679 break;
3680 case MATCH_PAIR:
3681 case MATCH_SAME:
3682 /* N directions (NSEW) * 3 dimensions of matching */
3683 fc_assert(count == 2);
3684 number = NUM_CORNER_DIRS * 2 * 2 * 2;
3685 break;
3686 case MATCH_FULL:
3687 default:
3688 /* N directions (NSEW) * 3 dimensions of matching */
3689 /* could use exp() or expi() here? */
3690 number = NUM_CORNER_DIRS * count * count * count;
3691 break;
3694 dlp->cells
3695 = fc_calloc(number, sizeof(*dlp->cells));
3697 for (i = 0; i < number; i++) {
3698 enum direction4 dir = i % NUM_CORNER_DIRS;
3699 int value = i / NUM_CORNER_DIRS;
3701 switch (dlp->match_style) {
3702 case MATCH_NONE:
3703 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
3704 l, draw->name, direction4letters[dir]);
3705 dlp->cells[i] =
3706 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3707 "cell terrain",
3708 terrain_rule_name(pterrain));
3709 break;
3710 case MATCH_SAME:
3711 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
3712 l, draw->name, direction4letters[dir],
3713 (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
3714 dlp->cells[i] =
3715 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3716 "same cell terrain",
3717 terrain_rule_name(pterrain));
3718 break;
3719 case MATCH_PAIR:
3720 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
3721 l, draw->name, direction4letters[dir],
3722 tslp->match_types[dlp->match_index[(value) & 1]][0],
3723 tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
3724 tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
3725 dlp->cells[i] =
3726 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3727 "cell pair terrain",
3728 terrain_rule_name(pterrain));
3729 break;
3730 case MATCH_FULL:
3732 int this = dlp->match_index[0];
3733 int n, s, e, w;
3734 int v1, v2, v3;
3736 v1 = dlp->match_index[value % count];
3737 value /= count;
3738 v2 = dlp->match_index[value % count];
3739 value /= count;
3740 v3 = dlp->match_index[value % count];
3742 fc_assert(v1 < count && v2 < count && v3 < count);
3744 /* Assume merged cells. This should be a separate option. */
3745 switch (dir) {
3746 case DIR4_NORTH:
3747 s = this;
3748 w = v1;
3749 n = v2;
3750 e = v3;
3751 break;
3752 case DIR4_EAST:
3753 w = this;
3754 n = v1;
3755 e = v2;
3756 s = v3;
3757 break;
3758 case DIR4_SOUTH:
3759 n = this;
3760 e = v1;
3761 s = v2;
3762 w = v3;
3763 break;
3764 case DIR4_WEST:
3765 default: /* avoid warnings */
3766 e = this;
3767 s = v1;
3768 w = v2;
3769 n = v3;
3770 break;
3773 /* Use first character of match_types,
3774 * already checked for uniqueness. */
3775 fc_snprintf(buffer, sizeof(buffer),
3776 "t.l%d.cellgroup_%c_%c_%c_%c", l,
3777 tslp->match_types[n][0], tslp->match_types[e][0],
3778 tslp->match_types[s][0], tslp->match_types[w][0]);
3779 sprite = load_sprite(t, buffer);
3781 if (sprite) {
3782 /* Crop the sprite to separate this cell. */
3783 int vec_size = sprite_vector_size(&dlp->allocated);
3785 const int W = t->normal_tile_width;
3786 const int H = t->normal_tile_height;
3787 int x[4] = {W / 4, W / 4, 0, W / 2};
3788 int y[4] = {H / 2, 0, H / 4, H / 4};
3789 int xo[4] = {0, 0, -W / 2, W / 2};
3790 int yo[4] = {H / 2, -H / 2, 0, 0};
3792 sprite = crop_sprite(sprite,
3793 x[dir], y[dir], W / 2, H / 2,
3794 t->sprites.mask.tile,
3795 xo[dir], yo[dir]);
3797 /* We allocated new sprite with crop_sprite. Store its
3798 * address so we can free it. */
3799 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
3800 dlp->allocated.p[vec_size] = sprite;
3801 } else {
3802 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer);
3805 dlp->cells[i] = sprite;
3807 break;
3811 break;
3815 /* try an optional special name */
3816 fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
3817 draw->blender =
3818 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, buffer, "",
3819 "blend terrain",
3820 terrain_rule_name(pterrain));
3822 if (draw->blending > 0) {
3823 const int bl = draw->blending - 1;
3825 if (NULL == draw->blender) {
3826 int li = 0;
3828 /* try an already loaded base */
3829 while (NULL == draw->blender
3830 && li < draw->blending
3831 && 0 < draw->layer[li].base.size) {
3832 draw->blender = draw->layer[li++].base.p[0];
3836 if (NULL == draw->blender) {
3837 /* try an unloaded base name */
3838 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", bl, draw->name);
3839 draw->blender =
3840 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3841 "base (blend) terrain",
3842 terrain_rule_name(pterrain));
3846 if (NULL != draw->blender) {
3847 /* Set up blending sprites. This only works in iso-view! */
3848 const int W = t->normal_tile_width;
3849 const int H = t->normal_tile_height;
3850 const int offsets[4][2] = {
3851 {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
3853 enum direction4 dir = 0;
3855 for (; dir < 4; dir++) {
3856 draw->blend[dir] = crop_sprite(draw->blender,
3857 offsets[dir][0], offsets[dir][1],
3858 W / 2, H / 2,
3859 t->sprites.dither_tile, 0, 0);
3863 draw->init = TRUE;
3864 t->sprites.drawing[terrain_index(pterrain)] = draw;
3867 /**********************************************************************
3868 Set government sprite value; should only happen after
3869 tilespec_load_tiles().
3870 ***********************************************************************/
3871 void tileset_setup_government(struct tileset *t,
3872 struct government *gov)
3874 t->sprites.government[government_index(gov)] =
3875 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, gov->graphic_str,
3876 gov->graphic_alt, "government",
3877 government_rule_name(gov));
3879 /* should probably do something if NULL, eg generic default? */
3882 /**********************************************************************
3883 Set nation flag sprite value; should only happen after
3884 tilespec_load_tiles().
3885 ***********************************************************************/
3886 void tileset_setup_nation_flag(struct tileset *t,
3887 struct nation_type *nation)
3889 char *tags[] = {nation->flag_graphic_str,
3890 nation->flag_graphic_alt,
3891 "unknown", NULL};
3892 int i;
3893 struct sprite *flag = NULL, *shield = NULL;
3894 char buf[1024];
3896 for (i = 0; tags[i] && !flag; i++) {
3897 fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
3898 flag = load_sprite(t, buf);
3900 for (i = 0; tags[i] && !shield; i++) {
3901 fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
3902 shield = load_sprite(t, buf);
3904 if (!flag || !shield) {
3905 /* Should never get here because of the f.unknown fallback. */
3906 tileset_error(LOG_FATAL, _("Nation %s: no national flag."), nation_rule_name(nation));
3909 sprite_vector_reserve(&t->sprites.nation_flag, nation_count());
3910 t->sprites.nation_flag.p[nation_index(nation)] = flag;
3912 sprite_vector_reserve(&t->sprites.nation_shield, nation_count());
3913 t->sprites.nation_shield.p[nation_index(nation)] = shield;
3916 /**********************************************************************
3917 Return the flag graphic to be used by the city.
3918 ***********************************************************************/
3919 struct sprite *get_city_flag_sprite(const struct tileset *t,
3920 const struct city *pcity)
3922 return get_nation_flag_sprite(t, nation_of_city(pcity));
3925 /**********************************************************************
3926 Return a sprite for the national flag for this unit.
3927 ***********************************************************************/
3928 static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
3929 const struct unit *punit)
3931 struct nation_type *pnation = nation_of_unit(punit);
3933 if (gui_options.draw_unit_shields) {
3934 return t->sprites.nation_shield.p[nation_index(pnation)];
3935 } else {
3936 return t->sprites.nation_flag.p[nation_index(pnation)];
3940 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
3941 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
3943 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
3944 (fc_assert(s != NULL), \
3945 sprs->sprite = s, \
3946 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
3947 sprs->offset_x = x_offset, \
3948 sprs->offset_y = y_offset, \
3949 sprs++)
3950 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
3951 #define ADD_SPRITE_FULL(s) \
3952 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
3954 /**************************************************************************
3955 Assemble some data that is used in building the tile sprite arrays.
3956 (map_x, map_y) : the (normalized) map position
3957 The values we fill in:
3958 tterrain_near : terrain types of all adjacent terrain
3959 tspecial_near : specials of all adjacent terrain
3960 **************************************************************************/
3961 static void build_tile_data(const struct tile *ptile,
3962 struct terrain *pterrain,
3963 struct terrain **tterrain_near,
3964 bv_extras *textras_near)
3966 enum direction8 dir;
3968 /* Loop over all adjacent tiles. We should have an iterator for this. */
3969 for (dir = 0; dir < 8; dir++) {
3970 struct tile *tile1 = mapstep(ptile, dir);
3972 if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
3973 struct terrain *terrain1 = tile_terrain(tile1);
3975 if (NULL != terrain1) {
3976 tterrain_near[dir] = terrain1;
3977 textras_near[dir] = *tile_extras(tile1);
3978 continue;
3980 log_error("build_tile_data() tile (%d,%d) has no terrain!",
3981 TILE_XY(tile1));
3983 /* At the edges of the (known) map, pretend the same terrain continued
3984 * past the edge of the map. */
3985 tterrain_near[dir] = pterrain;
3986 BV_CLR_ALL(textras_near[dir]);
3990 /**********************************************************************
3991 Fill in the sprite array for the unit type.
3992 ***********************************************************************/
3993 static int fill_unit_type_sprite_array(const struct tileset *t,
3994 struct drawn_sprite *sprs,
3995 const struct unit_type *putype,
3996 enum direction8 facing)
3998 struct drawn_sprite *save_sprs = sprs;
3999 struct sprite *uspr = get_unittype_sprite(t, putype, facing, FALSE);
4001 ADD_SPRITE(uspr, TRUE,
4002 FULL_TILE_X_OFFSET + t->unit_offset_x,
4003 FULL_TILE_Y_OFFSET + t->unit_offset_y);
4005 return sprs - save_sprs;
4008 /**********************************************************************
4009 Fill in the sprite array for the unit.
4010 ***********************************************************************/
4011 static int fill_unit_sprite_array(const struct tileset *t,
4012 struct drawn_sprite *sprs,
4013 const struct unit *punit,
4014 bool stack, bool backdrop)
4016 struct drawn_sprite *save_sprs = sprs;
4017 int ihp;
4018 struct unit_type *ptype = unit_type_get(punit);
4020 if (backdrop) {
4021 if (!gui_options.solid_color_behind_units) {
4022 ADD_SPRITE(get_unit_nation_flag_sprite(t, punit), TRUE,
4023 FULL_TILE_X_OFFSET + t->unit_flag_offset_x,
4024 FULL_TILE_Y_OFFSET + t->unit_flag_offset_y);
4025 } else {
4026 /* Taken care of in the LAYER_BACKGROUND. */
4030 /* Add the sprite for the unit type. */
4031 sprs += fill_unit_type_sprite_array(t, sprs, ptype,
4032 punit->facing);
4034 if (t->sprites.unit.loaded && unit_transported(punit)) {
4035 ADD_SPRITE_FULL(t->sprites.unit.loaded);
4038 if (punit->activity != ACTIVITY_IDLE) {
4039 struct sprite *s = NULL;
4041 switch (punit->activity) {
4042 case ACTIVITY_MINE:
4043 if (punit->activity_target == NULL) {
4044 s = t->sprites.unit.plant;
4045 } else {
4046 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4048 break;
4049 case ACTIVITY_IRRIGATE:
4050 if (punit->activity_target == NULL) {
4051 s = t->sprites.unit.irrigate;
4052 } else {
4053 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4055 break;
4056 case ACTIVITY_POLLUTION:
4057 case ACTIVITY_FALLOUT:
4058 s = t->sprites.extras[extra_index(punit->activity_target)].rmact;
4059 break;
4060 case ACTIVITY_PILLAGE:
4061 s = t->sprites.unit.pillage;
4062 break;
4063 case ACTIVITY_EXPLORE:
4064 s = t->sprites.unit.auto_explore;
4065 break;
4066 case ACTIVITY_FORTIFIED:
4067 s = t->sprites.unit.fortified;
4068 break;
4069 case ACTIVITY_FORTIFYING:
4070 s = t->sprites.unit.fortifying;
4071 break;
4072 case ACTIVITY_SENTRY:
4073 s = t->sprites.unit.sentry;
4074 break;
4075 case ACTIVITY_GOTO:
4076 s = t->sprites.unit.go_to;
4077 break;
4078 case ACTIVITY_TRANSFORM:
4079 s = t->sprites.unit.transform;
4080 break;
4081 case ACTIVITY_BASE:
4082 case ACTIVITY_GEN_ROAD:
4083 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4084 break;
4085 case ACTIVITY_CONVERT:
4086 s = t->sprites.unit.convert;
4087 break;
4088 default:
4089 break;
4092 if (s != NULL) {
4093 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4094 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4098 if (punit->ai_controlled && punit->activity != ACTIVITY_EXPLORE) {
4099 if (is_military_unit(punit)) {
4100 ADD_SPRITE_FULL(t->sprites.unit.auto_attack);
4101 } else {
4102 ADD_SPRITE_FULL(t->sprites.unit.auto_settler);
4106 if (unit_has_orders(punit)) {
4107 if (punit->orders.repeat) {
4108 ADD_SPRITE_FULL(t->sprites.unit.patrol);
4109 } else if (punit->activity != ACTIVITY_IDLE) {
4110 ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
4111 } else {
4112 ADD_SPRITE(t->sprites.unit.go_to, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4113 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4117 if (punit->battlegroup != BATTLEGROUP_NONE) {
4118 ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
4121 if (t->sprites.unit.lowfuel
4122 && utype_fuel(ptype)
4123 && punit->fuel == 1
4124 && punit->moves_left <= 2 * SINGLE_MOVE) {
4125 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4126 ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
4128 if (t->sprites.unit.tired
4129 && punit->moves_left < SINGLE_MOVE
4130 && ptype->move_rate > 0) {
4131 /* Show a "tired" graphic if the unit has fewer than one move
4132 * remaining, except for units for which it's full movement. */
4133 ADD_SPRITE_FULL(t->sprites.unit.tired);
4136 if (stack || punit->client.occupied) {
4137 ADD_SPRITE_FULL(t->sprites.unit.stack);
4140 if (t->sprites.unit.vet_lev[punit->veteran]) {
4141 ADD_SPRITE_FULL(t->sprites.unit.vet_lev[punit->veteran]);
4144 ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
4145 ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
4146 ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
4148 return sprs - save_sprs;
4151 /**************************************************************************
4152 Add any corner road sprites to the sprite array.
4153 **************************************************************************/
4154 static int fill_road_corner_sprites(const struct tileset *t,
4155 const struct extra_type *pextra,
4156 struct drawn_sprite *sprs,
4157 bool road, bool *road_near,
4158 bool hider, bool *hider_near)
4160 struct drawn_sprite *saved_sprs = sprs;
4161 int i;
4162 int extra_idx = extra_index(pextra);
4164 if (is_cardinal_only_road(pextra)) {
4165 return 0;
4168 /* Roads going diagonally adjacent to this tile need to be
4169 * partly drawn on this tile. */
4171 /* Draw the corner sprite if:
4172 * - There is a diagonal road (not rail!) between two adjacent tiles.
4173 * - There is no diagonal road (not rail!) that intersects this road.
4174 * The logic is simple: roads are drawn underneath railrods, but are
4175 * not always covered by them (even in the corners!). But if a railroad
4176 * connects two tiles, only the railroad (no road) is drawn between
4177 * those tiles.
4179 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4180 enum direction8 dir = t->valid_tileset_dirs[i];
4182 if (!is_cardinal_tileset_dir(t, dir)) {
4183 /* Draw corner sprites for this non-cardinal direction. */
4184 int cw = (i + 1) % t->num_valid_tileset_dirs;
4185 int ccw
4186 = (i + t->num_valid_tileset_dirs - 1) % t->num_valid_tileset_dirs;
4187 enum direction8 cwdir = t->valid_tileset_dirs[cw];
4188 enum direction8 ccwdir = t->valid_tileset_dirs[ccw];
4190 if (t->sprites.extras[extra_idx].u.road.corner[dir]
4191 && (road_near[cwdir] && road_near[ccwdir]
4192 && !(hider_near[cwdir] && hider_near[ccwdir]))
4193 && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
4194 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.corner[dir]);
4199 return sprs - saved_sprs;
4202 /**************************************************************************
4203 Fill all road and rail sprites into the sprite array.
4204 **************************************************************************/
4205 static int fill_road_sprite_array(const struct tileset *t,
4206 const struct extra_type *pextra,
4207 struct drawn_sprite *sprs,
4208 bv_extras textras,
4209 bv_extras *textras_near,
4210 struct terrain *tterrain_near[8],
4211 const struct city *pcity)
4213 struct drawn_sprite *saved_sprs = sprs;
4214 bool road, road_near[8], hider, hider_near[8];
4215 bool land_near[8], hland_near[8];
4216 bool draw_road[8], draw_single_road;
4217 enum direction8 dir;
4218 int extra_idx = -1;
4219 bool cl = FALSE;
4220 enum extrastyle_id extrastyle;
4221 const struct road_type *proad = extra_road_get(pextra);
4223 extra_idx = extra_index(pextra);
4225 extrastyle = t->sprites.extras[extra_idx].extrastyle;
4227 if (extra_has_flag(pextra, EF_CONNECT_LAND)) {
4228 cl = TRUE;
4229 } else {
4230 int i;
4232 for (i = 0; i < 8; i++) {
4233 land_near[i] = FALSE;
4237 /* Fill some data arrays. rail_near and road_near store whether road/rail
4238 * is present in the given direction. draw_rail and draw_road store
4239 * whether road/rail is to be drawn in that direction. draw_single_road
4240 * and draw_single_rail store whether we need an isolated road/rail to be
4241 * drawn. */
4242 road = BV_ISSET(textras, extra_idx);
4244 hider = FALSE;
4245 extra_type_list_iterate(pextra->hiders, phider) {
4246 if (BV_ISSET(textras, extra_index(phider))) {
4247 hider = TRUE;
4248 break;
4250 } extra_type_list_iterate_end;
4252 if (road && (!pcity || !gui_options.draw_cities) && !hider) {
4253 draw_single_road = TRUE;
4254 } else {
4255 draw_single_road = FALSE;
4258 for (dir = 0; dir < 8; dir++) {
4259 bool roads_exist;
4261 /* Check if there is adjacent road/rail. */
4262 if (!is_cardinal_only_road(pextra)
4263 || is_cardinal_tileset_dir(t, dir)) {
4264 road_near[dir] = FALSE;
4265 extra_type_list_iterate(proad->integrators, iextra) {
4266 if (BV_ISSET(textras_near[dir], extra_index(iextra))) {
4267 road_near[dir] = TRUE;
4268 break;
4270 } extra_type_list_iterate_end;
4271 if (cl) {
4272 land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
4273 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN);
4275 } else {
4276 road_near[dir] = FALSE;
4277 land_near[dir] = FALSE;
4280 /* Draw rail/road if there is a connection from this tile to the
4281 * adjacent tile. But don't draw road if there is also a rail
4282 * connection. */
4283 roads_exist = road && (road_near[dir] || land_near[dir]);
4284 draw_road[dir] = roads_exist;
4285 hider_near[dir] = FALSE;
4286 hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
4287 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN;
4288 extra_type_list_iterate(pextra->hiders, phider) {
4289 bool hider_dir = FALSE;
4290 bool land_dir = FALSE;
4292 if (!is_cardinal_only_road(phider)
4293 || is_cardinal_tileset_dir(t, dir)) {
4294 if (BV_ISSET(textras_near[dir], extra_index(phider))) {
4295 hider_near[dir] = TRUE;
4296 hider_dir = TRUE;
4298 if (hland_near[dir]
4299 && is_extra_caused_by(phider, EC_ROAD)
4300 && extra_has_flag(phider, EF_CONNECT_LAND)) {
4301 land_dir = TRUE;
4303 if (hider_dir || land_dir) {
4304 if (BV_ISSET(textras, extra_index(phider))) {
4305 draw_road[dir] = FALSE;
4309 } extra_type_list_iterate_end;
4311 /* Don't draw an isolated road/rail if there's any connection.
4312 * draw_single_road would be true in the first place only if start tile has road,
4313 * so it will have road connection with any adjacent road tile. We check from real
4314 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
4315 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
4316 * draw single road in that case either. */
4317 if (draw_single_road && road_near[dir]) {
4318 draw_single_road = FALSE;
4322 /* Draw road corners */
4323 sprs
4324 += fill_road_corner_sprites(t, pextra, sprs, road, road_near, hider, hider_near);
4326 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
4327 /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
4328 * This means we only need a few sprites, but a lot of drawing is
4329 * necessary and it generally doesn't look very good. */
4330 int i;
4332 /* First draw roads under rails. */
4333 if (road) {
4334 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4335 if (draw_road[t->valid_tileset_dirs[i]]) {
4336 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.dir[i]);
4340 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4341 /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
4342 * road connections, one sprite for diagonal road connections.
4343 * This means we need about 4x more sprites than in style 0, but up to
4344 * 4x less drawing is needed. The drawing quality may also be
4345 * improved. */
4347 /* First draw roads under rails. */
4348 if (road) {
4349 int road_even_tileno = 0, road_odd_tileno = 0, i;
4351 for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
4352 enum direction8 even = t->valid_tileset_dirs[2 * i];
4353 enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
4355 if (draw_road[even]) {
4356 road_even_tileno |= 1 << i;
4358 if (draw_road[odd]) {
4359 road_odd_tileno |= 1 << i;
4363 /* Draw the cardinal/even roads first. */
4364 if (road_even_tileno != 0) {
4365 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.even[road_even_tileno]);
4367 if (road_odd_tileno != 0) {
4368 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.odd[road_odd_tileno]);
4371 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4372 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
4373 * entire finished tiles, with a bitwise index of the presence of
4374 * roads in each direction. */
4376 /* Draw roads first */
4377 if (road) {
4378 int road_tileno = 0, i;
4380 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4381 enum direction8 vdir = t->valid_tileset_dirs[i];
4383 if (draw_road[vdir]) {
4384 road_tileno |= 1 << i;
4388 if (road_tileno != 0 || draw_single_road) {
4389 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.total[road_tileno]);
4392 } else {
4393 fc_assert(FALSE);
4396 /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
4397 ESTYLE_ROAD_PARITY_COMBINED only). */
4398 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4399 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4400 if (draw_single_road) {
4401 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.isolated);
4405 return sprs - saved_sprs;
4408 /**************************************************************************
4409 Return the index of the sprite to be used for irrigation or farmland in
4410 this tile.
4412 We assume that the current tile has farmland or irrigation. We then
4413 choose a sprite (index) based upon which cardinally adjacent tiles have
4414 either farmland or irrigation (the two are considered interchangable for
4415 this).
4416 **************************************************************************/
4417 static int get_irrigation_index(const struct tileset *t,
4418 struct extra_type *pextra,
4419 bv_extras *textras_near)
4421 int tileno = 0, i;
4423 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4424 enum direction8 dir = t->cardinal_tileset_dirs[i];
4426 if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
4427 tileno |= 1 << i;
4431 return tileno;
4434 /**************************************************************************
4435 Fill in the farmland/irrigation sprite for the tile.
4436 **************************************************************************/
4437 static int fill_irrigation_sprite_array(const struct tileset *t,
4438 struct drawn_sprite *sprs,
4439 bv_extras textras,
4440 bv_extras *textras_near,
4441 const struct city *pcity)
4443 struct drawn_sprite *saved_sprs = sprs;
4445 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4446 * anyway, and ends up looking bad). */
4447 if (!(pcity && gui_options.draw_cities)) {
4448 extra_type_list_iterate(t->style_lists[ESTYLE_CARDINALS], pextra) {
4449 if (is_extra_drawing_enabled(pextra)) {
4450 int eidx = extra_index(pextra);
4452 if (BV_ISSET(textras, eidx)) {
4453 bool hidden = FALSE;
4455 extra_type_list_iterate(pextra->hiders, phider) {
4456 if (BV_ISSET(textras, extra_index(phider))) {
4457 hidden = TRUE;
4458 break;
4460 } extra_type_list_iterate_end;
4462 if (!hidden) {
4463 int idx = get_irrigation_index(t, pextra, textras_near);
4465 ADD_SPRITE_SIMPLE(t->sprites.extras[eidx].u.cardinals[idx]);
4469 } extra_type_list_iterate_end;
4472 return sprs - saved_sprs;
4475 /**************************************************************************
4476 Fill in the city overlays for the tile. This includes the citymap
4477 overlays on the mapview as well as the tile output sprites.
4478 **************************************************************************/
4479 static int fill_city_overlays_sprite_array(const struct tileset *t,
4480 struct drawn_sprite *sprs,
4481 const struct tile *ptile,
4482 const struct city *citymode)
4484 const struct city *pcity;
4485 const struct city *pwork;
4486 struct unit *psettler;
4487 struct drawn_sprite *saved_sprs = sprs;
4488 int city_x, city_y;
4489 const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
4491 if (NULL == ptile || TILE_UNKNOWN == client_tile_get_known(ptile)) {
4492 return 0;
4494 pwork = tile_worked(ptile);
4496 if (citymode) {
4497 pcity = citymode;
4498 } else {
4499 pcity = find_city_or_settler_near_tile(ptile, &psettler);
4502 /* Below code does not work if pcity is invisible.
4503 * Make sure it is not. */
4504 fc_assert_ret_val(pcity == NULL || pcity->tile != NULL, 0);
4505 if (pcity && !pcity->tile) {
4506 pcity = NULL;
4509 if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
4510 /* FIXME: check elsewhere for valid tile (instead of above) */
4512 if (!citymode && pcity->client.colored) {
4513 /* Add citymap overlay for a city. */
4514 int idx = pcity->client.color_index % NUM_CITY_COLORS;
4516 if (NULL != pwork && pwork == pcity) {
4517 ADD_SPRITE_SIMPLE(t->sprites.city.worked_tile_overlay.p[idx]);
4518 } else if (city_can_work_tile(pcity, ptile)) {
4519 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4521 } else if (NULL != pwork && pwork == pcity
4522 && (citymode || gui_options.draw_city_output)) {
4523 /* Add on the tile output sprites. */
4524 int food = city_tile_output_now(pcity, ptile, O_FOOD);
4525 int shields = city_tile_output_now(pcity, ptile, O_SHIELD);
4526 int trade = city_tile_output_now(pcity, ptile, O_TRADE);
4527 const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
4528 const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
4530 food = CLIP(0, food, NUM_TILES_DIGITS - 1);
4531 shields = CLIP(0, shields, NUM_TILES_DIGITS - 1);
4532 trade = CLIP(0, trade, NUM_TILES_DIGITS - 1);
4534 ADD_SPRITE(t->sprites.city.tile_foodnum[food], TRUE, ox, oy);
4535 ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
4536 ADD_SPRITE(t->sprites.city.tile_tradenum[trade], TRUE, ox, oy);
4538 } else if (psettler && psettler->client.colored) {
4539 /* Add citymap overlay for a unit. */
4540 int idx = psettler->client.color_index % NUM_CITY_COLORS;
4542 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4545 return sprs - saved_sprs;
4548 /****************************************************************************
4549 Helper function for fill_terrain_sprite_layer.
4550 Fill in the sprite array for blended terrain.
4551 ****************************************************************************/
4552 static int fill_terrain_sprite_blending(const struct tileset *t,
4553 struct drawn_sprite *sprs,
4554 const struct tile *ptile,
4555 const struct terrain *pterrain,
4556 struct terrain **tterrain_near)
4558 struct drawn_sprite *saved_sprs = sprs;
4559 const int W = t->normal_tile_width, H = t->normal_tile_height;
4560 const int offsets[4][2] = {
4561 {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4563 enum direction4 dir = 0;
4566 * We want to mark unknown tiles so that an unreal tile will be
4567 * given the same marking as our current tile - that way we won't
4568 * get the "unknown" dither along the edge of the map.
4570 for (; dir < 4; dir++) {
4571 struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
4572 struct terrain *other;
4574 if (!tile1
4575 || client_tile_get_known(tile1) == TILE_UNKNOWN
4576 || pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
4577 || (0 == t->sprites.drawing[terrain_index(other)]->blending
4578 && NULL == t->sprites.drawing[terrain_index(other)]->blender)) {
4579 continue;
4582 ADD_SPRITE(t->sprites.drawing[terrain_index(other)]->blend[dir], TRUE,
4583 offsets[dir][0], offsets[dir][1]);
4586 return sprs - saved_sprs;
4589 /****************************************************************************
4590 Add sprites for fog (and some forms of darkness).
4591 ****************************************************************************/
4592 static int fill_fog_sprite_array(const struct tileset *t,
4593 struct drawn_sprite *sprs,
4594 const struct tile *ptile,
4595 const struct tile_edge *pedge,
4596 const struct tile_corner *pcorner)
4598 struct drawn_sprite *saved_sprs = sprs;
4600 if (t->fogstyle == FOG_SPRITE && gui_options.draw_fog_of_war
4601 && NULL != ptile
4602 && TILE_KNOWN_UNSEEN == client_tile_get_known(ptile)) {
4603 /* With FOG_AUTO, fog is done this way. */
4604 ADD_SPRITE_SIMPLE(t->sprites.tx.fog);
4607 if (t->darkness_style == DARKNESS_CORNER && pcorner
4608 && gui_options.draw_fog_of_war) {
4609 int i, tileno = 0;
4611 for (i = 3; i >= 0; i--) {
4612 const int unknown = 0, fogged = 1, known = 2;
4613 int value = -1;
4615 if (!pcorner->tile[i]) {
4616 value = fogged;
4617 } else {
4618 switch (client_tile_get_known(pcorner->tile[i])) {
4619 case TILE_KNOWN_SEEN:
4620 value = known;
4621 break;
4622 case TILE_KNOWN_UNSEEN:
4623 value = fogged;
4624 break;
4625 case TILE_UNKNOWN:
4626 value = unknown;
4627 break;
4630 fc_assert(value >= 0 && value < 3);
4632 tileno = tileno * 3 + value;
4635 if (t->sprites.tx.fullfog[tileno]) {
4636 ADD_SPRITE_SIMPLE(t->sprites.tx.fullfog[tileno]);
4640 return sprs - saved_sprs;
4643 /****************************************************************************
4644 Helper function for fill_terrain_sprite_layer.
4645 ****************************************************************************/
4646 static int fill_terrain_sprite_array(struct tileset *t,
4647 struct drawn_sprite *sprs,
4648 int l, /* layer_num */
4649 const struct tile *ptile,
4650 const struct terrain *pterrain,
4651 struct terrain **tterrain_near,
4652 struct drawing_data *draw)
4654 struct drawn_sprite *saved_sprs = sprs;
4655 struct drawing_layer *dlp = &draw->layer[l];
4656 int this = dlp->match_index[0];
4657 int that = dlp->match_index[1];
4658 int ox = dlp->offset_x;
4659 int oy = dlp->offset_y;
4660 int i;
4662 #define MATCH(dir) \
4663 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4664 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4665 : -1)
4667 switch (dlp->sprite_type) {
4668 case CELL_WHOLE:
4670 switch (dlp->match_style) {
4671 case MATCH_NONE:
4673 int count = sprite_vector_size(&dlp->base);
4675 if (count > 0) {
4676 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4677 * to limit the number to a handleable size [0..32000). */
4678 count = fc_randomly(tile_index(ptile) % 32000, count);
4680 if (dlp->is_tall) {
4681 ox += FULL_TILE_X_OFFSET;
4682 oy += FULL_TILE_Y_OFFSET;
4684 ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
4686 break;
4688 case MATCH_SAME:
4690 int tileno = 0;
4692 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4693 enum direction8 dir = t->cardinal_tileset_dirs[i];
4695 if (MATCH(dir) == this) {
4696 tileno |= 1 << i;
4700 if (dlp->is_tall) {
4701 ox += FULL_TILE_X_OFFSET;
4702 oy += FULL_TILE_Y_OFFSET;
4704 ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
4705 break;
4707 case MATCH_PAIR:
4708 case MATCH_FULL:
4709 fc_assert(FALSE); /* not yet defined */
4710 break;
4712 break;
4714 case CELL_CORNER:
4716 /* Divide the tile up into four rectangular cells. Each of these
4717 * cells covers one corner, and each is adjacent to 3 different
4718 * tiles. For each cell we pick a sprite based upon the adjacent
4719 * terrains at each of those tiles. Thus, we have 8 different sprites
4720 * for each of the 4 cells (32 sprites total).
4722 * These arrays correspond to the direction4 ordering. */
4723 const int W = t->normal_tile_width;
4724 const int H = t->normal_tile_height;
4725 const int iso_offsets[4][2] = {
4726 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
4728 const int noniso_offsets[4][2] = {
4729 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
4732 /* put corner cells */
4733 for (i = 0; i < NUM_CORNER_DIRS; i++) {
4734 const int count = dlp->match_indices;
4735 int array_index = 0;
4736 enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
4737 int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
4738 int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
4739 int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
4740 struct sprite *s;
4742 /* synthesize 4 dimensional array? */
4743 switch (dlp->match_style) {
4744 case MATCH_NONE:
4745 /* We have no need for matching, just plug the piece in place. */
4746 break;
4747 case MATCH_SAME:
4748 array_index = array_index * 2 + (m[2] != this);
4749 array_index = array_index * 2 + (m[1] != this);
4750 array_index = array_index * 2 + (m[0] != this);
4751 break;
4752 case MATCH_PAIR:
4753 array_index = array_index * 2 + (m[2] == that);
4754 array_index = array_index * 2 + (m[1] == that);
4755 array_index = array_index * 2 + (m[0] == that);
4756 break;
4757 case MATCH_FULL:
4758 default:
4760 int n[3];
4761 int j = 0;
4762 for (; j < 3; j++) {
4763 int k = 0;
4764 for (; k < count; k++) {
4765 n[j] = k; /* default to last entry */
4766 if (m[j] == dlp->match_index[k])
4768 break;
4772 array_index = array_index * count + n[2];
4773 array_index = array_index * count + n[1];
4774 array_index = array_index * count + n[0];
4776 break;
4778 array_index = array_index * NUM_CORNER_DIRS + i;
4780 s = dlp->cells[array_index];
4781 if (s) {
4782 ADD_SPRITE(s, TRUE, x, y);
4785 break;
4788 #undef MATCH
4790 return sprs - saved_sprs;
4793 /****************************************************************************
4794 Helper function for fill_terrain_sprite_layer.
4795 Fill in the sprite array of darkness.
4796 ****************************************************************************/
4797 static int fill_terrain_sprite_darkness(struct tileset *t,
4798 struct drawn_sprite *sprs,
4799 const struct tile *ptile,
4800 struct terrain **tterrain_near)
4802 struct drawn_sprite *saved_sprs = sprs;
4803 int i, tileno;
4804 struct tile *adjc_tile;
4806 #define UNKNOWN(dir) \
4807 ((adjc_tile = mapstep(ptile, (dir))) \
4808 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4810 switch (t->darkness_style) {
4811 case DARKNESS_NONE:
4812 break;
4813 case DARKNESS_ISORECT:
4814 for (i = 0; i < 4; i++) {
4815 const int W = t->normal_tile_width, H = t->normal_tile_height;
4816 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
4818 if (UNKNOWN(DIR4_TO_DIR8[i])) {
4819 ADD_SPRITE(t->sprites.tx.darkness[i], TRUE,
4820 offsets[i][0], offsets[i][1]);
4823 break;
4824 case DARKNESS_CARD_SINGLE:
4825 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4826 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4827 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[i]);
4830 break;
4831 case DARKNESS_CARD_FULL:
4832 /* We're looking to find the INDEX_NSEW for the directions that
4833 * are unknown. We want to mark unknown tiles so that an unreal
4834 * tile will be given the same marking as our current tile - that
4835 * way we won't get the "unknown" dither along the edge of the
4836 * map. */
4837 tileno = 0;
4838 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4839 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4840 tileno |= 1 << i;
4844 if (tileno != 0) {
4845 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[tileno]);
4847 break;
4848 case DARKNESS_CORNER:
4849 /* Handled separately. */
4850 break;
4852 #undef UNKNOWN
4854 return sprs - saved_sprs;
4857 /****************************************************************************
4858 Add sprites for the base tile to the sprite list. This doesn't
4859 include specials or rivers.
4860 ****************************************************************************/
4861 static int fill_terrain_sprite_layer(struct tileset *t,
4862 struct drawn_sprite *sprs,
4863 int layer_num,
4864 const struct tile *ptile,
4865 const struct terrain *pterrain,
4866 struct terrain **tterrain_near)
4868 struct sprite *sprite;
4869 struct drawn_sprite *saved_sprs = sprs;
4870 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
4871 const int l = (draw->is_reversed
4872 ? (draw->num_layers - layer_num - 1) : layer_num);
4874 fc_assert(layer_num < TERRAIN_LAYER_COUNT);
4876 /* Skip the normal drawing process. */
4877 /* FIXME: this should avoid calling load_sprite since it's slow and
4878 * increases the refcount without limit. */
4879 if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite))) {
4880 if (l == 0) {
4881 ADD_SPRITE_SIMPLE(sprite);
4882 return 1;
4883 } else {
4884 return 0;
4888 if (l < draw->num_layers) {
4889 sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
4891 if ((l + 1) == draw->blending) {
4892 sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
4896 /* Add darkness on top of the designed terrain layer. Note that darkness is always
4897 * drawn, even in citymode, etc. */
4898 if (layer_num == t->darkness_layer) {
4899 sprs += fill_terrain_sprite_darkness(t, sprs, ptile, tterrain_near);
4902 return sprs - saved_sprs;
4905 /****************************************************************************
4906 Indicate whether a unit is to be drawn with a surrounding city outline
4907 under current conditions.
4908 (This includes being in focus, but if the caller has already checked that,
4909 they can bypass this slightly expensive check with check_focus == FALSE.)
4910 ****************************************************************************/
4911 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
4913 /* Display an outline for city-builder type units if they are selected,
4914 * and on a tile where a city can be built.
4915 * But suppress the outline if the unit has orders (likely it is in
4916 * transit to somewhere else and this will just slow down redraws). */
4917 return gui_options.draw_city_outlines
4918 && unit_is_cityfounder(punit)
4919 && !unit_has_orders(punit)
4920 && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN
4921 && city_can_be_built_here(unit_tile(punit), punit))
4922 && (!check_focus || unit_is_in_focus(punit));
4925 /****************************************************************************
4926 Fill in the grid sprites for the given tile, city, and unit.
4927 ****************************************************************************/
4928 static int fill_grid_sprite_array(const struct tileset *t,
4929 struct drawn_sprite *sprs,
4930 const struct tile *ptile,
4931 const struct tile_edge *pedge,
4932 const struct tile_corner *pcorner,
4933 const struct unit *punit,
4934 const struct city *pcity,
4935 const struct city *citymode)
4937 struct drawn_sprite *saved_sprs = sprs;
4939 if (pedge) {
4940 bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
4941 bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
4942 int i;
4943 struct unit_list *pfocus_units = get_units_in_focus();
4945 for (i = 0; i < NUM_EDGE_TILES; i++) {
4946 int dummy_x, dummy_y;
4947 const struct tile *tile = pedge->tile[i];
4948 struct player *powner = tile ? tile_owner(tile) : NULL;
4950 known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
4951 unit[i] = FALSE;
4952 if (tile && !citymode) {
4953 unit_list_iterate(pfocus_units, pfocus_unit) {
4954 if (unit_drawn_with_city_outline(pfocus_unit, FALSE)
4955 && city_tile_to_city_map(&dummy_x, &dummy_y,
4956 game.info.init_city_radius_sq,
4957 unit_tile(pfocus_unit), tile)) {
4958 unit[i] = TRUE;
4959 break;
4961 } unit_list_iterate_end;
4963 worked[i] = FALSE;
4965 city[i] = (tile
4966 && (NULL == powner || NULL == client.conn.playing
4967 || powner == client.conn.playing)
4968 && player_in_city_map(client.conn.playing, tile));
4969 if (city[i]) {
4970 if (citymode) {
4971 /* In citymode, we only draw worked tiles for this city - other
4972 * tiles may be marked as unavailable. */
4973 worked[i] = (tile_worked(tile) == citymode);
4974 } else {
4975 worked[i] = (NULL != tile_worked(tile));
4980 if (mapdeco_is_highlight_set(pedge->tile[0])
4981 || mapdeco_is_highlight_set(pedge->tile[1])) {
4982 ADD_SPRITE_SIMPLE(t->sprites.grid.selected[pedge->type]);
4983 } else if (!gui_options.draw_terrain && gui_options.draw_coastline
4984 && pedge->tile[0] && pedge->tile[1]
4985 && known[0] && known[1]
4986 && (is_ocean_tile(pedge->tile[0])
4987 ^ is_ocean_tile(pedge->tile[1]))) {
4988 ADD_SPRITE_SIMPLE(t->sprites.grid.coastline[pedge->type]);
4989 } else {
4990 if (gui_options.draw_map_grid) {
4991 if (worked[0] || worked[1]) {
4992 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
4993 } else if (city[0] || city[1]) {
4994 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
4995 } else if (known[0] || known[1]) {
4996 ADD_SPRITE_SIMPLE(t->sprites.grid.main[pedge->type]);
4999 if (gui_options.draw_city_outlines) {
5000 if (XOR(city[0], city[1])) {
5001 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5003 if (XOR(unit[0], unit[1])) {
5004 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5009 if (gui_options.draw_borders
5010 && BORDERS_DISABLED != game.info.borders
5011 && known[0]
5012 && known[1]) {
5013 struct player *owner0 = tile_owner(pedge->tile[0]);
5014 struct player *owner1 = tile_owner(pedge->tile[1]);
5016 if (owner0 != owner1) {
5017 if (owner0) {
5018 int plrid = player_index(owner0);
5019 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5020 [pedge->type][0]);
5022 if (owner1) {
5023 int plrid = player_index(owner1);
5024 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5025 [pedge->type][1]);
5029 } else if (NULL != ptile && TILE_UNKNOWN != client_tile_get_known(ptile)) {
5030 int cx, cy;
5032 if (citymode
5033 /* test to ensure valid coordinates? */
5034 && city_base_to_city_map(&cx, &cy, citymode, ptile)
5035 && !client_city_can_work_tile(citymode, ptile)) {
5036 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5039 if (gui_options.draw_native && citymode == NULL) {
5040 bool native = TRUE;
5041 struct unit_list *pfocus_units = get_units_in_focus();
5043 unit_list_iterate(pfocus_units, pfocus) {
5044 if (!is_native_tile(unit_type_get(pfocus), ptile)) {
5045 native = FALSE;
5046 break;
5048 } unit_list_iterate_end;
5050 if (!native) {
5051 if (t->sprites.grid.nonnative != NULL) {
5052 ADD_SPRITE_SIMPLE(t->sprites.grid.nonnative);
5053 } else {
5054 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5060 return sprs - saved_sprs;
5063 /****************************************************************************
5064 Fill in the given sprite array with any needed goto sprites.
5065 ****************************************************************************/
5066 static int fill_goto_sprite_array(const struct tileset *t,
5067 struct drawn_sprite *sprs,
5068 const struct tile *ptile,
5069 const struct tile_edge *pedge,
5070 const struct tile_corner *pcorner)
5072 struct drawn_sprite *saved_sprs = sprs;
5073 struct sprite *sprite;
5074 bool warn = FALSE;
5075 enum goto_tile_state state;
5076 int length;
5077 bool waypoint;
5079 if (goto_tile_state(ptile, &state, &length, &waypoint)) {
5080 if (length >= 0) {
5081 fc_assert(state >= 0);
5082 fc_assert(state < ARRAY_SIZE(t->sprites.path.s));
5084 sprite = t->sprites.path.s[state].specific;
5085 if (sprite != NULL) {
5086 ADD_SPRITE(sprite, FALSE, 0, 0);
5089 sprite = t->sprites.path.s[state].turns[length % 10];
5090 ADD_SPRITE_SIMPLE(sprite);
5091 if (length >= 10) {
5092 sprite = t->sprites.path.s[state].turns_tens[(length / 10) % 10];
5093 ADD_SPRITE_SIMPLE(sprite);
5094 if (length >= 100) {
5095 sprite = t->sprites.path.s[state].turns_hundreds[(length / 100)
5096 % 10];
5098 if (sprite != NULL) {
5099 ADD_SPRITE_SIMPLE(sprite);
5100 if (length >= 1000) {
5101 warn = TRUE;
5103 } else {
5104 warn = TRUE;
5110 if (waypoint) {
5111 ADD_SPRITE(t->sprites.path.waypoint, FALSE, 0, 0);
5114 if (warn) {
5115 /* Warn only once by tileset. */
5116 static char last_reported[256] = "";
5118 if (0 != strcmp(last_reported, t->name)) {
5119 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5120 "such as %d. Path not displayed as expected."),
5121 t->name, length);
5122 sz_strlcpy(last_reported, t->name);
5127 return sprs - saved_sprs;
5130 /****************************************************************************
5131 Should the given extra be drawn
5132 ****************************************************************************/
5133 static bool is_extra_drawing_enabled(struct extra_type *pextra)
5135 bool no_disable = TRUE; /* Draw if matches no cause */
5137 if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
5138 if (gui_options.draw_irrigation) {
5139 return TRUE;
5141 no_disable = FALSE;
5143 if (is_extra_caused_by(pextra, EC_POLLUTION)
5144 || is_extra_caused_by(pextra, EC_FALLOUT)) {
5145 if (gui_options.draw_pollution) {
5146 return TRUE;
5148 no_disable = FALSE;
5150 if (is_extra_caused_by(pextra, EC_MINE)) {
5151 if (gui_options.draw_mines) {
5152 return TRUE;
5154 no_disable = FALSE;
5156 if (is_extra_caused_by(pextra, EC_HUT)) {
5157 if (gui_options.draw_huts) {
5158 return TRUE;
5160 no_disable = FALSE;
5162 if (is_extra_caused_by(pextra, EC_BASE)) {
5163 if (gui_options.draw_fortress_airbase) {
5164 return TRUE;
5166 no_disable = FALSE;
5168 if (is_extra_caused_by(pextra, EC_ROAD)) {
5169 if (gui_options.draw_roads_rails) {
5170 return TRUE;
5172 no_disable = FALSE;
5175 return no_disable;
5178 /****************************************************************************
5179 Fill in the sprite array for the given tile, city, and unit.
5181 ptile, if specified, gives the tile. If specified the terrain and specials
5182 will be drawn for this tile. In this case (map_x,map_y) should give the
5183 location of the tile.
5185 punit, if specified, gives the unit. For tile drawing this should
5186 generally be get_drawable_unit(); otherwise it can be any unit.
5188 pcity, if specified, gives the city. For tile drawing this should
5189 generally be tile_city(ptile); otherwise it can be any city.
5191 citymode specifies whether this is part of a citydlg. If so some drawing
5192 is done differently.
5193 ****************************************************************************/
5194 int fill_sprite_array(struct tileset *t,
5195 struct drawn_sprite *sprs, enum mapview_layer layer,
5196 const struct tile *ptile,
5197 const struct tile_edge *pedge,
5198 const struct tile_corner *pcorner,
5199 const struct unit *punit, const struct city *pcity,
5200 const struct city *citymode,
5201 const struct unit_type *putype)
5203 int tileno, dir;
5204 bv_extras textras_near[8];
5205 bv_extras textras;
5206 struct terrain *tterrain_near[8];
5207 struct terrain *pterrain = NULL;
5208 struct drawn_sprite *save_sprs = sprs;
5209 struct player *owner = NULL;
5210 /* Unit drawing is disabled when the view options are turned off,
5211 * but only where we're drawing on the mapview. */
5212 bool do_draw_unit = (punit && (gui_options.draw_units || !ptile
5213 || (gui_options.draw_focus_unit
5214 && unit_is_in_focus(punit))));
5215 bool solid_bg = (gui_options.solid_color_behind_units
5216 && (do_draw_unit
5217 || (pcity && gui_options.draw_cities)
5218 || (ptile && !gui_options.draw_terrain)));
5220 if (citymode) {
5221 int count = 0, i, cx, cy;
5222 const struct tile *const *tiles = NULL;
5223 bool valid = FALSE;
5225 if (ptile) {
5226 tiles = &ptile;
5227 count = 1;
5228 } else if (pcorner) {
5229 tiles = pcorner->tile;
5230 count = NUM_CORNER_TILES;
5231 } else if (pedge) {
5232 tiles = pedge->tile;
5233 count = NUM_EDGE_TILES;
5236 for (i = 0; i < count; i++) {
5237 if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
5238 valid = TRUE;
5239 break;
5242 if (!valid) {
5243 return 0;
5247 if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
5248 textras = *tile_extras(ptile);
5249 pterrain = tile_terrain(ptile);
5251 if (NULL != pterrain) {
5252 if (layer == LAYER_TERRAIN1
5253 || layer == LAYER_TERRAIN2
5254 || layer == LAYER_TERRAIN3
5255 || layer == LAYER_WATER
5256 || layer == LAYER_ROADS) {
5257 build_tile_data(ptile, pterrain, tterrain_near, textras_near);
5259 } else {
5260 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
5261 TILE_XY(ptile));
5263 } else {
5264 BV_CLR_ALL(textras);
5267 switch (layer) {
5268 case LAYER_BACKGROUND:
5269 /* Set up background color. */
5270 if (gui_options.solid_color_behind_units) {
5271 if (do_draw_unit) {
5272 owner = unit_owner(punit);
5273 } else if (pcity && gui_options.draw_cities) {
5274 owner = city_owner(pcity);
5277 if (owner) {
5278 ADD_SPRITE_SIMPLE(t->sprites.player[player_index(owner)].background);
5279 } else if (ptile && !gui_options.draw_terrain) {
5280 ADD_SPRITE_SIMPLE(t->sprites.background.graphic);
5282 break;
5284 case LAYER_TERRAIN1:
5285 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5286 sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
5288 break;
5290 case LAYER_TERRAIN2:
5291 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5292 sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
5294 break;
5296 case LAYER_TERRAIN3:
5297 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5298 fc_assert(MAX_NUM_LAYERS == 3);
5299 sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
5301 break;
5303 case LAYER_WATER:
5304 if (NULL != pterrain) {
5305 if (gui_options.draw_terrain && !solid_bg
5306 && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
5307 for (dir = 0; dir < t->num_cardinal_tileset_dirs; dir++) {
5308 int didx = t->cardinal_tileset_dirs[dir];
5310 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5311 int idx = extra_index(priver);
5313 if (BV_ISSET(textras_near[didx], idx)) {
5314 if (t->sprites.extras[idx].u.road.ru.rivers.outlet[dir] != NULL) {
5315 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.outlet[dir]);
5317 break;
5319 } extra_type_list_iterate_end;
5323 sprs += fill_irrigation_sprite_array(t, sprs, textras, textras_near,
5324 pcity);
5326 if (gui_options.draw_terrain && !solid_bg) {
5327 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5328 int idx = extra_index(priver);
5330 if (BV_ISSET(textras, idx)) {
5331 int i;
5333 /* Draw rivers on top of irrigation. */
5334 tileno = 0;
5335 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5336 enum direction8 cdir = t->cardinal_tileset_dirs[i];
5338 if (terrain_type_terrain_class(tterrain_near[cdir]) == TC_OCEAN
5339 || BV_ISSET(textras_near[cdir], idx)) {
5340 tileno |= 1 << i;
5344 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[tileno]);
5346 } extra_type_list_iterate_end;
5349 break;
5351 case LAYER_ROADS:
5352 if (NULL != pterrain) {
5353 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_SEPARATE], pextra) {
5354 if (is_extra_drawing_enabled(pextra)) {
5355 sprs += fill_road_sprite_array(t, pextra, sprs,
5356 textras, textras_near,
5357 tterrain_near, pcity);
5359 } extra_type_list_iterate_end;
5360 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_PARITY_COMBINED], pextra) {
5361 if (is_extra_drawing_enabled(pextra)) {
5362 sprs += fill_road_sprite_array(t, pextra, sprs,
5363 textras, textras_near,
5364 tterrain_near, pcity);
5366 } extra_type_list_iterate_end;
5367 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_COMBINED], pextra) {
5368 if (is_extra_drawing_enabled(pextra)) {
5369 sprs += fill_road_sprite_array(t, pextra, sprs,
5370 textras, textras_near,
5371 tterrain_near, pcity);
5373 } extra_type_list_iterate_end;
5375 break;
5377 case LAYER_SPECIAL1:
5378 if (NULL != pterrain) {
5379 if (gui_options.draw_specials) {
5380 if (tile_resource_is_valid(ptile)) {
5381 ADD_SPRITE_SIMPLE(t->sprites.resource[resource_index(tile_resource(ptile))]);
5385 if (ptile) {
5386 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5387 if (tile_has_extra(ptile, pextra)
5388 && is_extra_drawing_enabled(pextra)
5389 && t->sprites.extras[extra_index(pextra)].u.bmf.background) {
5390 bool hidden = FALSE;
5392 extra_type_list_iterate(pextra->hiders, phider) {
5393 if (BV_ISSET(textras, extra_index(phider))) {
5394 hidden = TRUE;
5395 break;
5397 } extra_type_list_iterate_end;
5399 if (!hidden) {
5400 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.background);
5403 } extra_type_list_iterate_end;
5406 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE1], pextra) {
5407 if (BV_ISSET(textras, extra_index(pextra))
5408 && is_extra_drawing_enabled(pextra)) {
5409 bool hidden = FALSE;
5411 extra_type_list_iterate(pextra->hiders, phider) {
5412 if (BV_ISSET(textras, extra_index(phider))) {
5413 hidden = TRUE;
5414 break;
5416 } extra_type_list_iterate_end;
5418 if (!hidden) {
5419 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5422 } extra_type_list_iterate_end;
5424 break;
5426 case LAYER_GRID1:
5427 if (t->type == TS_ISOMETRIC) {
5428 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5429 punit, pcity, citymode);
5431 break;
5433 case LAYER_CITY1:
5434 /* City. Some city sprites are drawn later. */
5435 if (pcity && gui_options.draw_cities) {
5436 if (!gui_options.draw_full_citybar && !gui_options.solid_color_behind_units) {
5437 ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
5438 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5439 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5441 /* For iso-view the city.wall graphics include the full city, whereas
5442 * for non-iso view they are an overlay on top of the base city
5443 * graphic. */
5444 if (t->type == TS_OVERHEAD || pcity->client.walls <= 0) {
5445 ADD_SPRITE(get_city_sprite(t->sprites.city.tile, pcity), TRUE,
5446 FULL_TILE_X_OFFSET + t->city_offset_x,
5447 FULL_TILE_Y_OFFSET + t->city_offset_y);
5449 if (t->type == TS_ISOMETRIC && pcity->client.walls > 0) {
5450 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5451 struct sprite *spr = NULL;
5453 if (cspr != NULL) {
5454 spr = get_city_sprite(cspr, pcity);
5456 if (spr == NULL) {
5457 cspr = t->sprites.city.single_wall;
5458 if (cspr != NULL) {
5459 spr = get_city_sprite(cspr, pcity);
5463 if (spr != NULL) {
5464 ADD_SPRITE(spr, TRUE,
5465 FULL_TILE_X_OFFSET + t->city_offset_x,
5466 FULL_TILE_Y_OFFSET + t->city_offset_y);
5469 if (!gui_options.draw_full_citybar && pcity->client.occupied) {
5470 ADD_SPRITE(get_city_sprite(t->sprites.city.occupied, pcity), TRUE,
5471 FULL_TILE_X_OFFSET + t->occupied_offset_x,
5472 FULL_TILE_Y_OFFSET + t->occupied_offset_y);
5474 if (t->type == TS_OVERHEAD && pcity->client.walls > 0) {
5475 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5476 struct sprite *spr = NULL;
5478 if (cspr != NULL) {
5479 spr = get_city_sprite(cspr, pcity);
5481 if (spr == NULL) {
5482 cspr = t->sprites.city.single_wall;
5483 if (cspr != NULL) {
5484 spr = get_city_sprite(cspr, pcity);
5488 if (spr != NULL) {
5489 ADD_SPRITE_FULL(spr);
5492 if (pcity->client.unhappy) {
5493 ADD_SPRITE_FULL(t->sprites.city.disorder);
5496 break;
5498 case LAYER_SPECIAL2:
5499 if (NULL != pterrain) {
5500 if (ptile) {
5501 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5502 if (tile_has_extra(ptile, pextra)
5503 && is_extra_drawing_enabled(pextra)
5504 && t->sprites.extras[extra_index(pextra)].u.bmf.middleground) {
5505 bool hidden = FALSE;
5507 extra_type_list_iterate(pextra->hiders, phider) {
5508 if (BV_ISSET(textras, extra_index(phider))) {
5509 hidden = TRUE;
5510 break;
5512 } extra_type_list_iterate_end;
5514 if (!hidden) {
5515 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.middleground);
5518 } extra_type_list_iterate_end;
5521 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE2], pextra) {
5522 if (BV_ISSET(textras, extra_index(pextra))
5523 && is_extra_drawing_enabled(pextra)) {
5524 bool hidden = FALSE;
5526 extra_type_list_iterate(pextra->hiders, phider) {
5527 if (BV_ISSET(textras, extra_index(phider))) {
5528 hidden = TRUE;
5529 break;
5531 } extra_type_list_iterate_end;
5533 if (!hidden) {
5534 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5537 } extra_type_list_iterate_end;
5539 break;
5541 case LAYER_UNIT:
5542 case LAYER_FOCUS_UNIT:
5543 if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
5544 bool stacked = ptile && (unit_list_size(ptile->units) > 1);
5545 bool backdrop = !pcity;
5547 if (ptile && unit_is_in_focus(punit)
5548 && t->sprites.unit.select[0]) {
5549 /* Special case for drawing the selection rectangle. The blinking
5550 * unit is handled separately, inside get_drawable_unit(). */
5551 ADD_SPRITE_SIMPLE(t->sprites.unit.select[focus_unit_state]);
5554 sprs += fill_unit_sprite_array(t, sprs, punit, stacked, backdrop);
5555 } else if (putype != NULL && layer == LAYER_UNIT) {
5556 /* Only the sprite for the unit type. */
5557 sprs += fill_unit_type_sprite_array(t, sprs, putype,
5558 direction8_invalid());
5560 break;
5562 case LAYER_SPECIAL3:
5563 if (NULL != pterrain) {
5564 if (ptile) {
5565 bool show_flag = FALSE;
5566 struct player *eowner = extra_owner(ptile);
5568 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5569 if (is_extra_drawing_enabled(pextra)
5570 && tile_has_extra(ptile, pextra)
5571 && t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5572 bool hidden = FALSE;
5574 extra_type_list_iterate(pextra->hiders, phider) {
5575 if (BV_ISSET(textras, extra_index(phider))) {
5576 hidden = TRUE;
5577 break;
5579 } extra_type_list_iterate_end;
5581 if (!hidden) {
5582 if (t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5583 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.foreground);
5587 } extra_type_list_iterate_end;
5589 /* Show base flag. Not part of previous iteration as
5590 * "extras of ESTYLE_3_LAYER" != "bases" */
5591 if (eowner != NULL) {
5592 extra_type_list_iterate(t->flagged_bases_list, pextra) {
5593 if (tile_has_extra(ptile, pextra)) {
5594 bool hidden = FALSE;
5596 extra_type_list_iterate(pextra->hiders, phider) {
5597 if (BV_ISSET(textras, extra_index(phider))) {
5598 hidden = TRUE;
5599 break;
5601 } extra_type_list_iterate_end;
5603 if (!hidden) {
5604 show_flag = TRUE;
5607 } extra_type_list_iterate_end;
5609 if (show_flag) {
5610 ADD_SPRITE(get_nation_flag_sprite(t, nation_of_player(eowner)), TRUE,
5611 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5612 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5617 break;
5619 case LAYER_FOG:
5620 sprs += fill_fog_sprite_array(t, sprs, ptile, pedge, pcorner);
5621 break;
5623 case LAYER_CITY2:
5624 /* City size. Drawing this under fog makes it hard to read. */
5625 if (pcity && gui_options.draw_cities && !gui_options.draw_full_citybar) {
5626 bool warn = FALSE;
5628 ADD_SPRITE(t->sprites.city.size[city_size_get(pcity) % 10],
5629 FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5630 if (10 <= city_size_get(pcity)) {
5631 ADD_SPRITE(t->sprites.city.size_tens[(city_size_get(pcity) / 10)
5632 % 10], FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5633 if (100 <= city_size_get(pcity)) {
5634 struct sprite *sprite =
5635 t->sprites.city.size_hundreds[(city_size_get(pcity) / 100) % 10];
5637 if (NULL != sprite) {
5638 ADD_SPRITE(sprite, FALSE,
5639 FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5640 } else {
5641 warn = TRUE;
5643 if (1000 <= city_size_get(pcity)) {
5644 warn = TRUE;
5649 if (warn) {
5650 /* Warn only once by tileset. */
5651 static char last_reported[256] = "";
5653 if (0 != strcmp(last_reported, t->name)) {
5654 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5655 "such as %d. Size not displayed as expected."),
5656 t->name, city_size_get(pcity));
5657 sz_strlcpy(last_reported, t->name);
5661 break;
5663 case LAYER_GRID2:
5664 if (t->type == TS_OVERHEAD) {
5665 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5666 punit, pcity, citymode);
5668 break;
5670 case LAYER_OVERLAYS:
5671 sprs += fill_city_overlays_sprite_array(t, sprs, ptile, citymode);
5672 if (mapdeco_is_crosshair_set(ptile)) {
5673 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5675 break;
5677 case LAYER_CITYBAR:
5678 case LAYER_TILELABEL:
5679 /* Nothing. This is just a placeholder. */
5680 break;
5682 case LAYER_GOTO:
5683 if (ptile && goto_is_active()) {
5684 sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
5686 break;
5688 case LAYER_WORKERTASK:
5689 if (citymode != NULL && ptile != NULL) {
5690 worker_task_list_iterate(citymode->task_reqs, ptask) {
5691 if (ptask->ptile == ptile) {
5692 switch (ptask->act) {
5693 case ACTIVITY_MINE:
5694 if (ptask->tgt == NULL) {
5695 ADD_SPRITE_SIMPLE(t->sprites.unit.plant);
5696 } else {
5697 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5699 break;
5700 case ACTIVITY_IRRIGATE:
5701 if (ptask->tgt == NULL) {
5702 ADD_SPRITE_SIMPLE(t->sprites.unit.irrigate);
5703 } else {
5704 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5706 break;
5707 case ACTIVITY_GEN_ROAD:
5708 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5709 break;
5710 case ACTIVITY_TRANSFORM:
5711 ADD_SPRITE_SIMPLE(t->sprites.unit.transform);
5712 break;
5713 default:
5714 break;
5717 } worker_task_list_iterate_end;
5719 break;
5721 case LAYER_EDITOR:
5722 if (ptile && editor_is_active()) {
5723 if (editor_tile_is_selected(ptile)) {
5724 int color = 2 % tileset_num_city_colors(tileset);
5725 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
5728 if (NULL != map_startpos_get(ptile)) {
5729 /* FIXME: Use a more representative sprite. */
5730 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5733 break;
5735 case LAYER_COUNT:
5736 fc_assert(FALSE);
5737 break;
5740 return sprs - save_sprs;
5743 /**********************************************************************
5744 Set city tiles sprite values; should only happen after
5745 tilespec_load_tiles().
5746 ***********************************************************************/
5747 void tileset_setup_city_tiles(struct tileset *t, int style)
5749 if (style == game.control.styles_count - 1) {
5750 int i;
5752 /* Free old sprites */
5753 free_city_sprite(t->sprites.city.tile);
5755 for (i = 0; i < NUM_WALL_TYPES; i++) {
5756 free_city_sprite(t->sprites.city.wall[i]);
5757 t->sprites.city.wall[i] = NULL;
5759 free_city_sprite(t->sprites.city.single_wall);
5760 t->sprites.city.single_wall = NULL;
5762 free_city_sprite(t->sprites.city.occupied);
5764 t->sprites.city.tile = load_city_sprite(t, "city");
5766 for (i = 0; i < NUM_WALL_TYPES; i++) {
5767 char buffer[256];
5769 fc_snprintf(buffer, sizeof(buffer), "bldg_%d", i);
5770 t->sprites.city.wall[i] = load_city_sprite(t, buffer);
5772 t->sprites.city.single_wall = load_city_sprite(t, "wall");
5774 t->sprites.city.occupied = load_city_sprite(t, "occupied");
5776 for (style = 0; style < game.control.styles_count; style++) {
5777 if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
5778 tileset_error(LOG_FATAL, _("City style \"%s\": no city graphics."),
5779 city_style_rule_name(style));
5781 if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
5782 tileset_error(LOG_FATAL, _("City style \"%s\": no occupied graphics."),
5783 city_style_rule_name(style));
5789 /****************************************************************************
5790 Return the amount of time between calls to toggle_focus_unit_state.
5791 The main loop needs to call toggle_focus_unit_state about this often
5792 to do the active-unit animation.
5793 ****************************************************************************/
5794 double get_focus_unit_toggle_timeout(const struct tileset *t)
5796 if (t->sprites.unit.select[0]) {
5797 return 0.1;
5798 } else {
5799 return 0.5;
5803 /****************************************************************************
5804 Reset the focus unit state. This should be called when changing
5805 focus units.
5806 ****************************************************************************/
5807 void reset_focus_unit_state(struct tileset *t)
5809 focus_unit_state = 0;
5812 /****************************************************************************
5813 Setup tileset for showing combat where focus unit participates.
5814 ****************************************************************************/
5815 void focus_unit_in_combat(struct tileset *t)
5817 if (!t->sprites.unit.select[0]) {
5818 reset_focus_unit_state(t);
5822 /****************************************************************************
5823 Toggle/increment the focus unit state. This should be called once
5824 every get_focus_unit_toggle_timeout() seconds.
5825 ****************************************************************************/
5826 void toggle_focus_unit_state(struct tileset *t)
5828 focus_unit_state++;
5829 if (t->sprites.unit.select[0]) {
5830 focus_unit_state %= NUM_TILES_SELECT;
5831 } else {
5832 focus_unit_state %= 2;
5836 /**********************************************************************
5837 Find unit that we can display from given tile.
5838 ***********************************************************************/
5839 struct unit *get_drawable_unit(const struct tileset *t,
5840 struct tile *ptile,
5841 const struct city *citymode)
5843 struct unit *punit = find_visible_unit(ptile);
5845 if (punit == NULL) {
5846 return NULL;
5849 if (citymode && unit_owner(punit) == city_owner(citymode)) {
5850 return NULL;
5853 if (!unit_is_in_focus(punit)
5854 || t->sprites.unit.select[0] || focus_unit_state == 0) {
5855 return punit;
5856 } else {
5857 return NULL;
5861 /****************************************************************************
5862 This patch unloads all sprites from the sprite hash (the hash itself
5863 is left intact).
5864 ****************************************************************************/
5865 static void unload_all_sprites(struct tileset *t)
5867 if (t->sprite_hash) {
5868 sprite_hash_iterate(t->sprite_hash, tag_name, ss) {
5869 while (ss->ref_count > 0) {
5870 unload_sprite(t, tag_name);
5872 } sprite_hash_iterate_end;
5876 /**********************************************************************
5877 Free all sprites from tileset.
5878 ***********************************************************************/
5879 void tileset_free_tiles(struct tileset *t)
5881 int i;
5883 log_debug("tileset_free_tiles()");
5885 unload_all_sprites(t);
5887 free_city_sprite(t->sprites.city.tile);
5888 t->sprites.city.tile = NULL;
5890 for (i = 0; i < NUM_WALL_TYPES; i++) {
5891 free_city_sprite(t->sprites.city.wall[i]);
5892 t->sprites.city.wall[i] = NULL;
5894 free_city_sprite(t->sprites.city.single_wall);
5895 t->sprites.city.single_wall = NULL;
5897 free_city_sprite(t->sprites.city.occupied);
5898 t->sprites.city.occupied = NULL;
5900 if (t->sprite_hash) {
5901 sprite_hash_destroy(t->sprite_hash);
5902 t->sprite_hash = NULL;
5905 small_sprite_list_iterate(t->small_sprites, ss) {
5906 small_sprite_list_remove(t->small_sprites, ss);
5907 if (ss->file) {
5908 free(ss->file);
5910 fc_assert(ss->sprite == NULL);
5911 free(ss);
5912 } small_sprite_list_iterate_end;
5914 specfile_list_iterate(t->specfiles, sf) {
5915 specfile_list_remove(t->specfiles, sf);
5916 free(sf->file_name);
5917 if (sf->big_sprite) {
5918 free_sprite(sf->big_sprite);
5919 sf->big_sprite = NULL;
5921 free(sf);
5922 } specfile_list_iterate_end;
5924 sprite_vector_iterate(&t->sprites.city.worked_tile_overlay, psprite) {
5925 free_sprite(*psprite);
5926 } sprite_vector_iterate_end;
5927 sprite_vector_free(&t->sprites.city.worked_tile_overlay);
5929 sprite_vector_iterate(&t->sprites.city.unworked_tile_overlay, psprite) {
5930 free_sprite(*psprite);
5931 } sprite_vector_iterate_end;
5932 sprite_vector_free(&t->sprites.city.unworked_tile_overlay);
5934 if (t->sprites.tx.fullfog) {
5935 free(t->sprites.tx.fullfog);
5936 t->sprites.tx.fullfog = NULL;
5939 sprite_vector_free(&t->sprites.colors.overlays);
5940 sprite_vector_free(&t->sprites.explode.unit);
5941 sprite_vector_free(&t->sprites.nation_flag);
5942 sprite_vector_free(&t->sprites.nation_shield);
5943 sprite_vector_free(&t->sprites.citybar.occupancy);
5945 tileset_background_free(t);
5948 /**************************************************************************
5949 Return the sprite for drawing the given spaceship part.
5950 **************************************************************************/
5951 struct sprite *get_spaceship_sprite(const struct tileset *t,
5952 enum spaceship_part part)
5954 return t->sprites.spaceship[part];
5957 /**************************************************************************
5958 Return a sprite for the given citizen. The citizen's type is given,
5959 as well as their index (in the range [0..city_size_get(pcity))). The
5960 citizen's city can be used to determine which sprite to use (a NULL
5961 value indicates there is no city; i.e., the sprite is just being
5962 used as a picture).
5963 **************************************************************************/
5964 struct sprite *get_citizen_sprite(const struct tileset *t,
5965 enum citizen_category type,
5966 int citizen_index,
5967 const struct city *pcity)
5969 const struct citizen_graphic *graphic;
5970 int gfx_index = citizen_index;
5972 if (pcity != NULL) {
5973 gfx_index += pcity->client.first_citizen_index;
5976 if (type < CITIZEN_SPECIALIST) {
5977 fc_assert(type >= 0);
5978 graphic = &t->sprites.citizen[type];
5979 } else {
5980 fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
5981 graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
5984 if (graphic->count == 0) {
5985 return NULL;
5988 return graphic->sprite[gfx_index % graphic->count];
5991 /**************************************************************************
5992 Return the sprite for the nation.
5993 **************************************************************************/
5994 struct sprite *get_nation_flag_sprite(const struct tileset *t,
5995 const struct nation_type *pnation)
5997 return t->sprites.nation_flag.p[nation_index(pnation)];
6000 /**************************************************************************
6001 Return the shield sprite for the nation.
6002 **************************************************************************/
6003 struct sprite *get_nation_shield_sprite(const struct tileset *t,
6004 const struct nation_type *pnation)
6006 return t->sprites.nation_shield.p[nation_index(pnation)];
6009 /**************************************************************************
6010 Return the sprite for the technology/advance.
6011 **************************************************************************/
6012 struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
6014 fc_assert_ret_val(0 <= tech && tech < advance_count(), NULL);
6015 return t->sprites.tech[tech];
6018 /**************************************************************************
6019 Return the sprite for the building/improvement.
6020 **************************************************************************/
6021 struct sprite *get_building_sprite(const struct tileset *t,
6022 struct impr_type *pimprove)
6024 fc_assert_ret_val(NULL != pimprove, NULL);
6025 return t->sprites.building[improvement_index(pimprove)];
6028 /****************************************************************************
6029 Return the sprite for the government.
6030 ****************************************************************************/
6031 struct sprite *get_government_sprite(const struct tileset *t,
6032 const struct government *gov)
6034 fc_assert_ret_val(NULL != gov, NULL);
6035 return t->sprites.government[government_index(gov)];
6038 /****************************************************************************
6039 Return the sprite for the unit type (the base "unit" sprite).
6040 ****************************************************************************/
6041 struct sprite *get_unittype_sprite(const struct tileset *t,
6042 const struct unit_type *punittype,
6043 enum direction8 facing,
6044 bool icon)
6046 int uidx = utype_index(punittype);
6048 fc_assert_ret_val(NULL != punittype, NULL);
6050 if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
6051 /* Fallback to random orientation sprite.
6052 * The randomness was fixed at tileset load time for stability
6053 * (in tileset_setup_unit_type_from_tag()); here we need to adapt
6054 * that to the map topology (which is now known).
6055 * default_dir_seed was set to give uniform distribution for either
6056 * 6 or 8 valid directions.
6057 * Thus this direction is stable for a given unit type unless the
6058 * map topology changes. */
6059 unsigned int dir_index;
6061 fc_assert_ret_val(game.map.num_valid_dirs > 0, NULL);
6062 dir_index
6063 = t->sprites.units.default_dir_seed[uidx] % game.map.num_valid_dirs;
6064 facing = game.map.valid_dirs[dir_index];
6065 fc_assert_ret_val(is_valid_dir(facing), NULL);
6068 if (t->sprites.units.icon[uidx]
6069 && (icon || t->sprites.units.facing[uidx][facing] == NULL)) {
6070 /* Has icon sprite */
6071 return t->sprites.units.icon[uidx];
6072 } else {
6073 return t->sprites.units.facing[uidx][facing];
6077 /**************************************************************************
6078 Return a "sample" sprite for this city style.
6079 **************************************************************************/
6080 struct sprite *get_sample_city_sprite(const struct tileset *t,
6081 int style_idx)
6083 int num_thresholds =
6084 t->sprites.city.tile->styles[style_idx].land_num_thresholds;
6086 if (num_thresholds == 0) {
6087 return NULL;
6088 } else {
6089 return (t->sprites.city.tile->styles[style_idx]
6090 .land_thresholds[num_thresholds - 1].sprite);
6094 /**************************************************************************
6095 Return a sprite with an "arrow" theme graphic.
6096 **************************************************************************/
6097 struct sprite *get_arrow_sprite(const struct tileset *t,
6098 enum arrow_type arrow)
6100 fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, NULL);
6102 return t->sprites.arrow[arrow];
6105 /**************************************************************************
6106 Return a tax sprite for the given output type (usually gold/lux/sci).
6107 **************************************************************************/
6108 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype)
6110 switch (otype) {
6111 case O_SCIENCE:
6112 return t->sprites.tax_science;
6113 case O_GOLD:
6114 return t->sprites.tax_gold;
6115 case O_LUXURY:
6116 return t->sprites.tax_luxury;
6117 case O_TRADE:
6118 case O_FOOD:
6119 case O_SHIELD:
6120 case O_LAST:
6121 break;
6123 return NULL;
6126 /**************************************************************************
6127 Return event icon sprite
6128 **************************************************************************/
6129 struct sprite *get_event_sprite(const struct tileset *t, enum event_type event)
6131 return t->sprites.events[event];
6134 /**************************************************************************
6135 Return a thumbs-up/thumbs-down sprite to show treaty approval or
6136 disapproval.
6137 **************************************************************************/
6138 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
6140 return t->sprites.treaty_thumb[on_off ? 1 : 0];
6143 /**************************************************************************
6144 Return a sprite_vector containing the animation sprites for a unit
6145 explosion.
6146 **************************************************************************/
6147 const struct sprite_vector *get_unit_explode_animation(const struct
6148 tileset *t)
6150 return &t->sprites.explode.unit;
6153 /****************************************************************************
6154 Return a sprite contining the single nuke graphic.
6156 TODO: This should be an animation like the unit explode animation.
6157 ****************************************************************************/
6158 struct sprite *get_nuke_explode_sprite(const struct tileset *t)
6160 return t->sprites.explode.nuke;
6163 /**************************************************************************
6164 Return all the sprites used for city bar drawing.
6165 **************************************************************************/
6166 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
6168 if (gui_options.draw_full_citybar) {
6169 return &t->sprites.citybar;
6170 } else {
6171 return NULL;
6175 /**************************************************************************
6176 Return all the sprites used for editor icons, images, etc.
6177 **************************************************************************/
6178 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
6180 return &t->sprites.editor;
6183 /**************************************************************************
6184 Returns a sprite for the given cursor. The "hot" coordinates (the
6185 active coordinates of the mouse relative to the sprite) are placed int
6186 (*hot_x, *hot_y).
6187 A cursor can consist of several frames to be used for animation.
6188 **************************************************************************/
6189 struct sprite *get_cursor_sprite(const struct tileset *t,
6190 enum cursor_type cursor,
6191 int *hot_x, int *hot_y, int frame)
6193 *hot_x = t->sprites.cursor[cursor].hot_x;
6194 *hot_y = t->sprites.cursor[cursor].hot_y;
6195 return t->sprites.cursor[cursor].frame[frame];
6198 /****************************************************************************
6199 Return a sprite for the given icon. Icons are used by the operating
6200 system/window manager. Usually freeciv has to tell the OS what icon to
6201 use.
6203 Note that this function will return NULL before the sprites are loaded.
6204 The GUI code must be sure to call tileset_load_tiles before setting the
6205 top-level icon.
6206 ****************************************************************************/
6207 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
6209 return t->sprites.icon[icon];
6212 /****************************************************************************
6213 Returns a sprite with the "user-attention" crosshair graphic.
6215 FIXME: This function shouldn't be needed if the attention graphics are
6216 drawn natively by the tileset code.
6217 ****************************************************************************/
6218 struct sprite *get_attention_crosshair_sprite(const struct tileset *t)
6220 return t->sprites.user.attention;
6223 /****************************************************************************
6224 Returns a sprite for the given indicator with the given index. The
6225 index should be in [0, NUM_TILES_PROGRESS).
6226 ****************************************************************************/
6227 struct sprite *get_indicator_sprite(const struct tileset *t,
6228 enum indicator_type indicator,
6229 int idx)
6231 idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
6233 fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, NULL);
6235 return t->sprites.indicator[indicator][idx];
6238 /****************************************************************************
6239 Return a sprite for the unhappiness of the unit - to be shown as an
6240 overlay on the unit in the city support dialog, for instance.
6242 May return NULL if there's no unhappiness.
6243 ****************************************************************************/
6244 struct sprite *get_unit_unhappy_sprite(const struct tileset *t,
6245 const struct unit *punit,
6246 int happy_cost)
6248 const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
6250 if (unhappy > 0) {
6251 return t->sprites.upkeep.unhappy[unhappy - 1];
6252 } else {
6253 return NULL;
6257 /****************************************************************************
6258 Return a sprite for the upkeep of the unit - to be shown as an overlay
6259 on the unit in the city support dialog, for instance.
6261 May return NULL if there's no upkeep of the kind.
6262 ****************************************************************************/
6263 struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
6264 Output_type_id otype,
6265 const struct unit *punit,
6266 const int *upkeep_cost)
6268 const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES + 1);
6270 if (upkeep > 0) {
6271 return t->sprites.upkeep.output[otype][upkeep - 1];
6272 } else {
6273 return NULL;
6277 /****************************************************************************
6278 Return a rectangular sprite containing a fog "color". This can be used
6279 for drawing fog onto arbitrary areas (like the overview).
6280 ****************************************************************************/
6281 struct sprite *get_basic_fog_sprite(const struct tileset *t)
6283 return t->sprites.tx.fog;
6286 /****************************************************************************
6287 Return the tileset's color system.
6288 ****************************************************************************/
6289 struct color_system *get_color_system(const struct tileset *t)
6291 return t->color_system;
6294 /****************************************************************************
6295 Loads preferred theme if there's any.
6296 ****************************************************************************/
6297 void tileset_use_preferred_theme(const struct tileset *t)
6299 char *default_theme_name = NULL;
6300 size_t default_theme_name_sz = 0;
6301 int i;
6303 switch (get_gui_type()) {
6304 case GUI_GTK2:
6305 default_theme_name = gui_options.gui_gtk2_default_theme_name;
6306 default_theme_name_sz = sizeof(gui_options.gui_gtk2_default_theme_name);
6307 break;
6308 case GUI_GTK3:
6309 default_theme_name = gui_options.gui_gtk3_default_theme_name;
6310 default_theme_name_sz = sizeof(gui_options.gui_gtk3_default_theme_name);
6311 break;
6312 case GUI_GTK3_22:
6313 default_theme_name = gui_options.gui_gtk3_22_default_theme_name;
6314 default_theme_name_sz = sizeof(gui_options.gui_gtk3_22_default_theme_name);
6315 break;
6316 case GUI_SDL:
6317 default_theme_name = gui_options.gui_sdl_default_theme_name;
6318 default_theme_name_sz = sizeof(gui_options.gui_sdl_default_theme_name);
6319 break;
6320 case GUI_SDL2:
6321 default_theme_name = gui_options.gui_sdl2_default_theme_name;
6322 default_theme_name_sz = sizeof(gui_options.gui_sdl2_default_theme_name);
6323 break;
6324 case GUI_STUB:
6325 case GUI_XAW:
6326 case GUI_QT:
6327 case GUI_WEB:
6328 break;
6331 if (NULL == default_theme_name || 0 == default_theme_name_sz) {
6332 /* Theme is not supported by this client. */
6333 return;
6336 for (i = 0; i < t->num_preferred_themes; i++) {
6337 if (strcmp(t->preferred_themes[i], default_theme_name)) {
6338 if (popup_theme_suggestion_dialog(t->preferred_themes[i])) {
6339 log_debug("trying theme \"%s\".", t->preferred_themes[i]);
6340 if (load_theme(t->preferred_themes[i])) {
6341 (void) fc_strlcpy(default_theme_name, t->preferred_themes[i],
6342 default_theme_name_sz);
6343 return;
6348 log_verbose("The tileset doesn't specify preferred themes or none of its "
6349 "preferred themes can be used. Using system default.");
6350 gui_clear_theme();
6353 /****************************************************************************
6354 Initialize tileset structure
6355 ****************************************************************************/
6356 void tileset_init(struct tileset *t)
6358 int wi;
6360 /* We currently have no city sprites loaded. */
6361 t->sprites.city.tile = NULL;
6363 for (wi = 0; wi < NUM_WALL_TYPES; wi++) {
6364 t->sprites.city.wall[wi] = NULL;
6366 t->sprites.city.single_wall = NULL;
6368 t->sprites.city.occupied = NULL;
6370 t->sprites.background.color = NULL;
6371 t->sprites.background.graphic = NULL;
6373 player_slots_iterate(pslot) {
6374 int edge, j, id = player_slot_index(pslot);
6376 for (edge = 0; edge < EDGE_COUNT; edge++) {
6377 for (j = 0; j < 2; j++) {
6378 t->sprites.player[id].grid_borders[edge][j] = NULL;
6382 t->sprites.player[id].color = NULL;
6383 t->sprites.player[id].background = NULL;
6384 } player_slots_iterate_end;
6386 t->max_upkeep_height = 0;
6389 /****************************************************************************
6390 Fill the sprite array with sprites that together make a representative
6391 image of the given terrain type. Suitable for use as an icon and in list
6392 views.
6394 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
6395 Using other values for 'layer' here will result in undefined behaviour. ;)
6396 ****************************************************************************/
6397 int fill_basic_terrain_layer_sprite_array(struct tileset *t,
6398 struct drawn_sprite *sprs,
6399 int layer,
6400 struct terrain *pterrain)
6402 struct drawn_sprite *save_sprs = sprs;
6403 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
6405 struct terrain *tterrain_near[8];
6406 bv_special tspecial_near[8];
6408 struct tile dummy_tile; /* :( */
6410 int i;
6413 memset(&dummy_tile, 0, sizeof(struct tile));
6415 for (i = 0; i < 8; i++) {
6416 tterrain_near[i] = pterrain;
6417 BV_CLR_ALL(tspecial_near[i]);
6420 i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
6421 sprs += fill_terrain_sprite_array(t, sprs, i, &dummy_tile,
6422 pterrain, tterrain_near, draw);
6424 return sprs - save_sprs;
6427 /****************************************************************************
6428 Return the sprite for the given resource type.
6429 ****************************************************************************/
6430 struct sprite *get_resource_sprite(const struct tileset *t,
6431 const struct resource *presource)
6433 if (presource == NULL) {
6434 return NULL;
6437 return t->sprites.resource[resource_index(presource)];
6440 /****************************************************************************
6441 Return a representative sprite for the given extra type.
6442 ****************************************************************************/
6443 int fill_basic_extra_sprite_array(const struct tileset *t,
6444 struct drawn_sprite *sprs,
6445 const struct extra_type *pextra)
6447 int idx = extra_index(pextra);
6448 struct drawn_sprite *saved_sprs = sprs;
6450 switch (t->sprites.extras[idx].extrastyle) {
6451 case ESTYLE_SINGLE1:
6452 case ESTYLE_SINGLE2:
6453 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.single);
6454 break;
6455 case ESTYLE_CARDINALS:
6456 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.cardinals[0]);
6457 break;
6458 case ESTYLE_ROAD_ALL_SEPARATE:
6459 case ESTYLE_ROAD_PARITY_COMBINED:
6460 case ESTYLE_ROAD_ALL_COMBINED:
6461 case ESTYLE_RIVER:
6462 return fill_basic_road_sprite_array(t, sprs, pextra);
6463 case ESTYLE_3LAYER:
6464 return fill_basic_base_sprite_array(t, sprs, pextra);
6465 case ESTYLE_COUNT:
6466 fc_assert(t->sprites.extras[idx].extrastyle != ESTYLE_COUNT);
6467 break;
6470 return sprs - saved_sprs;
6473 /****************************************************************************
6474 Fills the sprite array with sprites that together make a representative
6475 image of the given road type. The image is suitable for use as an icon
6476 for the road type, for example.
6477 ****************************************************************************/
6478 int fill_basic_road_sprite_array(const struct tileset *t,
6479 struct drawn_sprite *sprs,
6480 const struct extra_type *pextra)
6482 struct drawn_sprite *saved_sprs = sprs;
6483 int idx;
6484 int i;
6485 enum extrastyle_id extrastyle;
6487 if (!t || !sprs || !pextra) {
6488 return 0;
6491 idx = extra_index(pextra);
6493 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6494 return 0;
6497 extrastyle = t->sprites.extras[idx].extrastyle;
6499 if (extrastyle == ESTYLE_RIVER) {
6500 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[0]);
6501 } else {
6502 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
6503 if (!t->valid_tileset_dirs[i]) {
6504 continue;
6506 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
6507 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.dir[i]);
6508 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
6509 if ((i % 2) == 0) {
6510 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.combo.even[1 << (i / 2)]);
6512 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
6513 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.total[1 << i]);
6518 return sprs - saved_sprs;
6521 /****************************************************************************
6522 Fills the sprite array with sprites that together make a representative
6523 image of the given base type. The image is suitable for use as an icon
6524 for the base type, for example.
6525 ****************************************************************************/
6526 int fill_basic_base_sprite_array(const struct tileset *t,
6527 struct drawn_sprite *sprs,
6528 const struct extra_type *pextra)
6530 struct drawn_sprite *saved_sprs = sprs;
6531 int idx;
6533 if (!t || !sprs || !pextra) {
6534 return 0;
6537 idx = extra_index(pextra);
6539 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6540 return 0;
6543 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
6544 if ((x) != NULL) {\
6545 ADD_SPRITE_FULL(x);\
6547 } while (0)
6549 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
6550 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.background);
6551 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.middleground);
6552 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.foreground);
6554 #undef ADD_SPRITE_IF_NOT_NULL
6556 return sprs - saved_sprs;
6559 /****************************************************************************
6560 Setup tiles for one player using the player color.
6561 ****************************************************************************/
6562 void tileset_player_init(struct tileset *t, struct player *pplayer)
6564 int plrid, i, j;
6565 struct sprite *color;
6567 fc_assert_ret(pplayer != NULL);
6569 plrid = player_index(pplayer);
6570 fc_assert_ret(plrid >= 0);
6571 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6573 /* Free all data before recreating it. */
6574 tileset_player_free(t, plrid);
6576 if (player_has_color(t, pplayer)) {
6577 t->sprites.player[plrid].color = color
6578 = create_plr_sprite(get_player_color(t, pplayer));
6579 } else {
6580 /* XXX: if player hasn't been assigned a color, perhaps there's no
6581 * point proceeding with an arbitrary color; this should only happen
6582 * in pregame. Probably blank sprites would be better. */
6584 fc_assert_ret(t->sprites.background.color != NULL);
6586 color = t->sprites.background.color;
6589 t->sprites.player[plrid].background
6590 = crop_sprite(color, 0, 0,
6591 t->normal_tile_width, t->normal_tile_height,
6592 t->sprites.mask.tile, 0, 0);
6594 for (i = 0; i < EDGE_COUNT; i++) {
6595 for (j = 0; j < 2; j++) {
6596 struct sprite *s;
6598 if (color && t->sprites.grid.borders[i][j]) {
6599 s = crop_sprite(color, 0, 0,
6600 t->normal_tile_width, t->normal_tile_height,
6601 t->sprites.grid.borders[i][j], 0, 0);
6602 } else {
6603 s = t->sprites.grid.borders[i][j];
6605 t->sprites.player[plrid].grid_borders[i][j] = s;
6610 /****************************************************************************
6611 Free tiles for one player using the player color.
6612 ****************************************************************************/
6613 static void tileset_player_free(struct tileset *t, int plrid)
6615 int i, j;
6617 fc_assert_ret(plrid >= 0);
6618 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6620 if (t->sprites.player[plrid].color) {
6621 free_sprite(t->sprites.player[plrid].color);
6622 t->sprites.player[plrid].color = NULL;
6624 if (t->sprites.player[plrid].background) {
6625 free_sprite(t->sprites.player[plrid].background);
6626 t->sprites.player[plrid].background = NULL;
6629 for (i = 0; i < EDGE_COUNT; i++) {
6630 for (j = 0; j < 2; j++) {
6631 if (t->sprites.player[plrid].grid_borders[i][j]) {
6632 free_sprite(t->sprites.player[plrid].grid_borders[i][j]);
6633 t->sprites.player[plrid].grid_borders[i][j] = NULL;
6639 /****************************************************************************
6640 Setup tiles for the background.
6641 ****************************************************************************/
6642 void tileset_background_init(struct tileset *t)
6644 /* Free all data before recreating it. */
6645 tileset_background_free(t);
6647 /* generate background color */
6648 t->sprites.background.color
6649 = create_plr_sprite(ensure_color(game.plr_bg_color));
6651 /* Chop up and build the background graphics. */
6652 t->sprites.background.graphic
6653 = crop_sprite(t->sprites.background.color, 0, 0,
6654 t->normal_tile_width, t->normal_tile_height,
6655 t->sprites.mask.tile, 0, 0);
6658 /****************************************************************************
6659 Free tiles for the background.
6660 ****************************************************************************/
6661 void tileset_background_free(struct tileset *t)
6663 if (t->sprites.background.color) {
6664 free_sprite(t->sprites.background.color);
6665 t->sprites.background.color = NULL;
6668 if (t->sprites.background.graphic) {
6669 free_sprite(t->sprites.background.graphic);
6670 t->sprites.background.graphic = NULL;
6674 /****************************************************************************
6675 Reset tileset data specific to ruleset.
6676 ****************************************************************************/
6677 void tileset_ruleset_reset(struct tileset *t)
6679 int i;
6681 for (i = 0; i < ESTYLE_COUNT; i++) {
6682 if (t->style_lists[i] != NULL) {
6683 extra_type_list_destroy(t->style_lists[i]);
6684 t->style_lists[i] = extra_type_list_new();
6688 if (t->flagged_bases_list != NULL) {
6689 extra_type_list_destroy(t->flagged_bases_list);
6690 t->flagged_bases_list = extra_type_list_new();
6694 /****************************************************************************
6695 Is tileset in sane state?
6696 ****************************************************************************/
6697 bool tileset_is_fully_loaded(void)
6699 return !tileset_update;
6702 /****************************************************************************
6703 Return tileset name
6704 ****************************************************************************/
6705 const char *tileset_name_get(struct tileset *t)
6707 return t->given_name;
6710 /****************************************************************************
6711 Return tileset version
6712 ****************************************************************************/
6713 const char *tileset_version(struct tileset *t)
6715 return t->version;
6718 /****************************************************************************
6719 Return tileset description summary
6720 ****************************************************************************/
6721 const char *tileset_summary(struct tileset *t)
6723 return t->summary;
6726 /****************************************************************************
6727 Return tileset description body
6728 ****************************************************************************/
6729 const char *tileset_description(struct tileset *t)
6731 return t->description;
6734 /****************************************************************************
6735 Return tileset topology index
6736 ****************************************************************************/
6737 int tileset_topo_index(struct tileset *t)
6739 return t->ts_topo_idx;