Stop sharing requirement_unit_state_ereq().
[freeciv.git] / client / tilespec.c
blob541ab517f3463c99a6c2a7232e3a5363616767c5
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-tilespec-Devel-2016-Jun-07 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-spec-Devel-2015-Mar-25"
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 } units;
242 struct sprite_vector nation_flag;
243 struct sprite_vector nation_shield;
245 struct citizen_graphic {
246 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
247 * sprites, as defined by the tileset. */
248 int count;
249 struct sprite *sprite[MAX_NUM_CITIZEN_SPRITES];
250 } citizen[CITIZEN_LAST], specialist[SP_MAX];
251 struct sprite *spaceship[SPACESHIP_COUNT];
252 struct {
253 int hot_x, hot_y;
254 struct sprite *frame[NUM_CURSOR_FRAMES];
255 } cursor[CURSOR_LAST];
256 struct {
257 struct sprite_vector unit;
258 struct sprite *nuke;
259 } explode;
260 struct {
261 struct sprite
262 *hp_bar[NUM_TILES_HP_BAR],
263 *vet_lev[MAX_VET_LEVELS],
264 *select[NUM_TILES_SELECT],
265 *auto_attack,
266 *auto_settler,
267 *auto_explore,
268 *fortified,
269 *fortifying,
270 *go_to, /* goto is a C keyword :-) */
271 *irrigate,
272 *plant,
273 *pillage,
274 *sentry,
275 *stack,
276 *loaded,
277 *transform,
278 *connect,
279 *patrol,
280 *convert,
281 *battlegroup[MAX_NUM_BATTLEGROUPS],
282 *action_decision_want,
283 *lowfuel,
284 *tired;
285 } unit;
286 struct {
287 struct sprite
288 *unhappy[MAX_NUM_UPKEEP_SPRITES],
289 *output[O_LAST][MAX_NUM_UPKEEP_SPRITES];
290 } upkeep;
291 struct {
292 struct sprite
293 *disorder,
294 *size[NUM_TILES_DIGITS],
295 *size_tens[NUM_TILES_DIGITS],
296 *size_hundreds[NUM_TILES_DIGITS],
297 *tile_foodnum[NUM_TILES_DIGITS],
298 *tile_shieldnum[NUM_TILES_DIGITS],
299 *tile_tradenum[NUM_TILES_DIGITS];
300 struct city_sprite
301 *tile,
302 *single_wall,
303 *wall[NUM_WALL_TYPES],
304 *occupied;
305 struct sprite_vector worked_tile_overlay;
306 struct sprite_vector unworked_tile_overlay;
307 } city;
308 struct citybar_sprites citybar;
309 struct editor_sprites editor;
310 struct {
311 struct {
312 struct sprite *specific;
313 struct sprite *turns[NUM_TILES_DIGITS];
314 struct sprite *turns_tens[NUM_TILES_DIGITS];
315 struct sprite *turns_hundreds[NUM_TILES_DIGITS];
316 } s[GTS_COUNT];
317 struct sprite *waypoint;
318 } path;
319 struct {
320 struct sprite *attention;
321 } user;
322 struct {
323 struct sprite
324 *fog,
325 **fullfog,
326 *darkness[MAX_INDEX_CARDINAL]; /* first unused */
327 } tx; /* terrain extra */
328 struct {
329 struct sprite
330 *activity,
331 *rmact;
332 enum extrastyle_id extrastyle;
333 union {
334 struct sprite *single;
335 struct sprite *cardinals[MAX_INDEX_CARDINAL];
336 struct {
337 struct sprite
338 *background,
339 *middleground,
340 *foreground;
341 } bmf;
342 struct {
343 struct sprite
344 /* for extrastyles ESTYLE_ROAD_ALL_SEPARATE and ESTYLE_ROAD_PARITY_COMBINED */
345 *isolated,
346 *corner[8]; /* Indexed by direction; only non-cardinal dirs used. */
347 union {
348 /* for ESTYLE_ROAD_ALL_SEPARATE */
349 struct sprite *dir[8]; /* all entries used */
350 /* ESTYLE_ROAD_PARITY_COMBINED */
351 struct {
352 struct sprite
353 *even[MAX_INDEX_HALF], /* first unused */
354 *odd[MAX_INDEX_HALF]; /* first unused */
355 } combo;
356 /* ESTYLE_ALL_SEPARATE */
357 struct sprite *total[MAX_INDEX_VALID];
358 struct river_sprites rivers;
359 } ru;
360 } road;
361 } u;
362 } extras[MAX_EXTRA_TYPES];
363 struct {
364 struct sprite
365 *main[EDGE_COUNT],
366 *city[EDGE_COUNT],
367 *worked[EDGE_COUNT],
368 *unavailable,
369 *nonnative,
370 *selected[EDGE_COUNT],
371 *coastline[EDGE_COUNT],
372 *borders[EDGE_COUNT][2];
373 } grid;
374 struct {
375 struct sprite_vector overlays;
376 } colors;
377 struct {
378 struct sprite *color; /* Generic background color */
379 struct sprite *graphic; /* Generic background graphic */
380 } background;
381 struct {
382 struct sprite *grid_borders[EDGE_COUNT][2];
383 struct sprite *color;
384 struct sprite *background;
385 } player[MAX_NUM_PLAYER_SLOTS];
387 struct drawing_data *drawing[MAX_NUM_ITEMS];
390 struct specfile {
391 struct sprite *big_sprite;
392 char *file_name;
395 #define SPECLIST_TAG specfile
396 #define SPECLIST_TYPE struct specfile
397 #include "speclist.h"
399 #define specfile_list_iterate(list, pitem) \
400 TYPED_LIST_ITERATE(struct specfile, list, pitem)
401 #define specfile_list_iterate_end LIST_ITERATE_END
404 * Information about an individual sprite. All fields except 'sprite' are
405 * filled at the time of the scan of the specfile. 'Sprite' is
406 * set/cleared on demand in load_sprite/unload_sprite.
408 struct small_sprite {
409 int ref_count;
411 /* The sprite is in this file. */
412 char *file;
414 /* Or, the sprite is in this file at the location. */
415 struct specfile *sf;
416 int x, y, width, height;
418 /* A little more (optional) data. */
419 int hot_x, hot_y;
421 struct sprite *sprite;
424 /* 'struct small_sprite_list' and related functions. */
425 #define SPECLIST_TAG small_sprite
426 #define SPECLIST_TYPE struct small_sprite
427 #include "speclist.h"
428 #define small_sprite_list_iterate(list, pitem) \
429 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
430 #define small_sprite_list_iterate_end LIST_ITERATE_END
432 /* 'struct sprite_hash' and related functions. */
433 #define SPECHASH_TAG sprite
434 #define SPECHASH_ASTR_KEY_TYPE
435 #define SPECHASH_IDATA_TYPE struct small_sprite *
436 #include "spechash.h"
437 #define sprite_hash_iterate(hash, tag_name, sprite) \
438 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
439 hash, tag_name, sprite)
440 #define sprite_hash_iterate_end HASH_ITERATE_END
442 /* 'struct drawing_hash' and related functions. */
443 static void drawing_data_destroy(struct drawing_data *draw);
445 #define SPECHASH_TAG drawing
446 #define SPECHASH_CSTR_KEY_TYPE
447 #define SPECHASH_IDATA_TYPE struct drawing_data *
448 #define SPECHASH_IDATA_FREE drawing_data_destroy
449 #include "spechash.h"
451 #define SPECHASH_TAG estyle
452 #define SPECHASH_ASTR_KEY_TYPE
453 #define SPECHASH_ENUM_DATA_TYPE extrastyle_id
454 #include "spechash.h"
456 struct tileset {
457 char name[512];
458 char given_name[MAX_LEN_NAME];
459 char version[MAX_LEN_NAME];
460 int priority;
462 char *summary;
463 char *description;
464 float scale;
466 char *for_ruleset;
468 enum mapview_layer layer_order[LAYER_COUNT];
470 enum ts_type type;
471 int hex_width, hex_height;
472 int ts_topo_idx;
474 int normal_tile_width, normal_tile_height;
475 int full_tile_width, full_tile_height;
476 int unit_tile_width, unit_tile_height;
477 int small_sprite_width, small_sprite_height;
479 int max_upkeep_height;
481 char *main_intro_filename;
483 enum direction8 unit_default_orientation;
485 int city_names_font_size, city_productions_font_size;
487 enum fog_style fogstyle;
488 enum darkness_style darkness_style;
490 int unit_flag_offset_x, unit_flag_offset_y;
491 int city_flag_offset_x, city_flag_offset_y;
492 int unit_offset_x, unit_offset_y;
493 int city_offset_x, city_offset_y;
494 int city_size_offset_x, city_size_offset_y;
496 int citybar_offset_y;
497 int tilelabel_offset_y;
498 int activity_offset_x;
499 int activity_offset_y;
500 int select_offset_x;
501 int select_offset_y;
502 int occupied_offset_x;
503 int occupied_offset_y;
504 int unit_upkeep_offset_y;
505 int unit_upkeep_small_offset_y;
507 #define NUM_CORNER_DIRS 4
508 #define TILES_PER_CORNER 4
509 int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
510 int num_index_valid, num_index_cardinal;
511 enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
513 struct tileset_layer {
514 char **match_types;
515 size_t match_count;
516 } layers[MAX_NUM_LAYERS];
518 struct specfile_list *specfiles;
519 struct small_sprite_list *small_sprites;
521 /* This hash table maps tilespec tags to struct small_sprites. */
522 struct sprite_hash *sprite_hash;
524 /* This hash table maps terrain graphic strings to drawing data. */
525 struct drawing_hash *tile_hash;
527 struct estyle_hash *estyle_hash;
529 struct named_sprites sprites;
531 struct color_system *color_system;
533 struct extra_type_list *style_lists[ESTYLE_COUNT];
535 struct extra_type_list *flagged_bases_list;
537 int num_preferred_themes;
538 char** preferred_themes;
541 struct tileset *tileset;
543 int focus_unit_state = 0;
545 static bool tileset_update = FALSE;
547 static struct tileset *tileset_read_toplevel(const char *tileset_name,
548 bool verbose, int topology_id,
549 float scale);
551 static int fill_unit_type_sprite_array(const struct tileset *t,
552 struct drawn_sprite *sprs,
553 const struct unit_type *putype,
554 enum direction8 facing);
555 static int fill_unit_sprite_array(const struct tileset *t,
556 struct drawn_sprite *sprs,
557 const struct unit *punit,
558 bool stack, bool backdrop);
559 static bool load_river_sprites(struct tileset *t,
560 struct river_sprites *store, const char *tag_pfx);
562 static void tileset_setup_base(struct tileset *t,
563 const struct extra_type *pextra);
564 static void tileset_setup_road(struct tileset *t,
565 struct extra_type *pextra);
567 static bool is_extra_drawing_enabled(struct extra_type *pextra);
569 static int fill_basic_road_sprite_array(const struct tileset *t,
570 struct drawn_sprite *sprs,
571 const struct extra_type *pextra);
572 static int fill_basic_base_sprite_array(const struct tileset *t,
573 struct drawn_sprite *sprs,
574 const struct extra_type *pextra);
576 static void tileset_player_free(struct tileset *t, int plrid);
578 /****************************************************************************
579 Called when ever there's problem in ruleset/tileset compatibility
580 ****************************************************************************/
581 void tileset_error(enum log_level level, const char *format, ...)
583 char buf[2048];
584 va_list args;
586 va_start(args, format);
587 fc_vsnprintf(buf, sizeof(buf), format, args);
588 va_end(args);
590 log_base(level, "%s", buf);
592 if (level <= LOG_NORMAL) {
593 show_tileset_error(buf);
596 if (level == LOG_FATAL) {
597 exit(EXIT_FAILURE);
601 /****************************************************************************
602 Create a new drawing data.
603 ****************************************************************************/
604 static struct drawing_data *drawing_data_new(void)
606 struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
608 draw->name = NULL;
610 return draw;
613 /****************************************************************************
614 Free a drawing data.
615 ****************************************************************************/
616 static void drawing_data_destroy(struct drawing_data *draw)
618 int i;
620 fc_assert_ret(NULL != draw);
622 if (draw->name != NULL) {
623 free(draw->name);
625 for (i = 0; i < 4; i++) {
626 if (draw->blend[i]) {
627 free_sprite(draw->blend[i]);
630 for (i = 0; i < draw->num_layers; i++) {
631 int vec_size = sprite_vector_size(&draw->layer[i].allocated);
632 int j;
634 for (j = 0; j < vec_size; j++) {
635 free_sprite(draw->layer[i].allocated.p[j]);
638 sprite_vector_free(&draw->layer[i].base);
639 sprite_vector_free(&draw->layer[i].allocated);
640 free(draw->layer[i].cells);
642 free(draw);
645 /****************************************************************************
646 Return the name of the given tileset.
647 ****************************************************************************/
648 const char *tileset_basename(const struct tileset *t)
650 return t->name;
653 /****************************************************************************
654 Return whether the current tileset is isometric.
655 ****************************************************************************/
656 bool tileset_is_isometric(const struct tileset *t)
658 return t->type == TS_ISOMETRIC;
661 /****************************************************************************
662 Return the hex_width of the current tileset. For iso-hex tilesets this
663 value will be > 0 and is_isometric will be set.
664 ****************************************************************************/
665 int tileset_hex_width(const struct tileset *t)
667 return t->hex_width;
670 /****************************************************************************
671 Return the hex_height of the current tileset. For hex tilesets this
672 value will be > 0 and is_isometric will be set.
673 ****************************************************************************/
674 int tileset_hex_height(const struct tileset *t)
676 return t->hex_height;
679 /****************************************************************************
680 Return the tile width of the current tileset. This is the tesselation
681 width of the tiled plane. This means it's the width of the bounding box
682 of the basic map tile.
684 For best results:
685 - The value should be even (or a multiple of 4 in iso-view).
686 - In iso-view, the width should be twice the height (to give a
687 perspective of 30 degrees above the horizon).
688 - In non-iso-view, width and height should be equal (overhead
689 perspective).
690 - In hex or iso-hex view, remember this is the tesselation vector.
691 hex_width and hex_height then give the size of the side of the
692 hexagon. Calculating the dimensions of a "regular" hexagon or
693 iso-hexagon may be tricky.
694 However these requirements are not absolute and callers should not
695 depend on them (although some do).
696 ****************************************************************************/
697 int tileset_tile_width(const struct tileset *t)
699 return t->normal_tile_width;
702 /****************************************************************************
703 Return the tile height of the current tileset. This is the tesselation
704 height of the tiled plane. This means it's the height of the bounding box
705 of the basic map tile.
707 See also tileset_tile_width.
708 ****************************************************************************/
709 int tileset_tile_height(const struct tileset *t)
711 return t->normal_tile_height;
714 /****************************************************************************
715 Return the full tile width of the current tileset. This is the maximum
716 width that any mapview sprite will have.
718 Note: currently this is always equal to the tile width.
719 ****************************************************************************/
720 int tileset_full_tile_width(const struct tileset *t)
722 return t->full_tile_width;
725 /****************************************************************************
726 Return the full tile height of the current tileset. This is the maximum
727 height that any mapview sprite will have. This may be greater than the
728 tile width in which case the extra area is above the "normal" tile.
730 Some callers assume the full height is 50% larger than the height in
731 iso-view, and equal in non-iso view.
732 ****************************************************************************/
733 int tileset_full_tile_height(const struct tileset *t)
735 return t->full_tile_height;
738 /****************************************************************************
739 Return the unit tile width of the current tileset.
740 ****************************************************************************/
741 int tileset_unit_width(const struct tileset *t)
743 return t->unit_tile_width;
746 /****************************************************************************
747 Return the unit tile height of the current tileset.
748 ****************************************************************************/
749 int tileset_unit_height(const struct tileset *t)
751 return t->unit_tile_height;
754 /****************************************************************************
755 Calculate the height of a unit upkeep icons.
756 ****************************************************************************/
757 static int calculate_max_upkeep_height(const struct tileset *t)
759 int i;
760 int max = 0;
762 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
763 if (t->sprites.upkeep.unhappy[i] != NULL) {
764 int width, height;
766 /* TODO: We want only height, getting the width might waste CPU
767 * depending on gui-specific implementation. */
768 get_sprite_dimensions(t->sprites.upkeep.unhappy[i], &width, &height);
770 max = MAX(max, height);
774 output_type_iterate(o) {
775 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
776 if (t->sprites.upkeep.output[o][i] != NULL) {
777 int width, height;
779 /* TODO: We want only height, getting the width might waste CPU
780 * depending on gui-specific implementation. */
781 get_sprite_dimensions(t->sprites.upkeep.output[o][i], &width, &height);
783 max = MAX(max, height);
786 } output_type_iterate_end;
788 return max;
791 /****************************************************************************
792 Get the height of a unit upkeep icons.
793 ****************************************************************************/
794 static int tileset_upkeep_height(const struct tileset *t)
796 /* Return cached value */
797 return t->max_upkeep_height;
800 /****************************************************************************
801 Suitable canvas height for a unit icon that includes upkeep sprites.
802 ****************************************************************************/
803 int tileset_unit_with_upkeep_height(const struct tileset *t)
805 int uk_bottom = tileset_unit_layout_offset_y(tileset) + tileset_upkeep_height(tileset);
806 int u_bottom = tileset_unit_height(tileset);
808 return MAX(uk_bottom, u_bottom);
811 /****************************************************************************
812 Suitable canvas height for a unit icon that includes upkeep sprites,
813 using small space layout.
814 ****************************************************************************/
815 int tileset_unit_with_small_upkeep_height(const struct tileset *t)
817 int uk_bottom = tileset_unit_layout_small_offset_y(tileset) + tileset_upkeep_height(tileset);
818 int u_bottom = tileset_unit_height(tileset);
820 return MAX(uk_bottom, u_bottom);
823 /****************************************************************************
824 Offset to layout extra unit sprites, such as upkeep.
825 ****************************************************************************/
826 int tileset_unit_layout_offset_y(const struct tileset *t)
828 return t->unit_upkeep_offset_y;
831 /****************************************************************************
832 Offset to layout extra unit sprites, such as upkeep, requesting small
833 space layout.
834 ****************************************************************************/
835 int tileset_unit_layout_small_offset_y(const struct tileset *t)
837 return t->unit_upkeep_small_offset_y;
840 /****************************************************************************
841 Return the small sprite width of the current tileset. The small sprites
842 are used for various theme graphics (e.g., citymap citizens/specialists
843 as well as panel indicator icons).
844 ****************************************************************************/
845 int tileset_small_sprite_width(const struct tileset *t)
847 return t->small_sprite_width;
850 /****************************************************************************
851 Return the offset from the origin of the city tile at which to place the
852 city bar text.
853 ****************************************************************************/
854 int tileset_citybar_offset_y(const struct tileset *t)
856 return t->citybar_offset_y;
859 /****************************************************************************
860 Return the offset from the origin of the tile at which to place the
861 label text.
862 ****************************************************************************/
863 int tileset_tilelabel_offset_y(const struct tileset *t)
865 return t->tilelabel_offset_y;
868 /****************************************************************************
869 Returns tileset scale
870 ****************************************************************************/
871 float tileset_scale(const struct tileset *t)
873 return tileset->scale;
876 /****************************************************************************
877 Return the small sprite height of the current tileset. The small sprites
878 are used for various theme graphics (e.g., citymap citizens/specialists
879 as well as panel indicator icons).
880 ****************************************************************************/
881 int tileset_small_sprite_height(const struct tileset *t)
883 return t->small_sprite_height;
886 /****************************************************************************
887 Return the path within the data directories where the main intro graphics
888 file can be found. (It is left up to the GUI code to load and unload this
889 file.)
890 ****************************************************************************/
891 const char *tileset_main_intro_filename(const struct tileset *t)
893 return t->main_intro_filename;
896 /****************************************************************************
897 Return the number of possible colors for city overlays.
898 ****************************************************************************/
899 int tileset_num_city_colors(const struct tileset *t)
901 return t->sprites.city.worked_tile_overlay.size;
904 /****************************************************************************
905 Return TRUE if the client will use the code to generate the fog.
906 ****************************************************************************/
907 bool tileset_use_hard_coded_fog(const struct tileset *t)
909 return FOG_AUTO == t->fogstyle;
912 /**************************************************************************
913 Initialize.
914 **************************************************************************/
915 static struct tileset *tileset_new(void)
917 struct tileset *t = fc_calloc(1, sizeof(*t));
919 t->specfiles = specfile_list_new();
920 t->small_sprites = small_sprite_list_new();
921 return t;
924 /**************************************************************************
925 Return the tileset name of the direction. This is similar to
926 dir_get_name but you shouldn't change this or all tilesets will break.
927 **************************************************************************/
928 static const char *dir_get_tileset_name(enum direction8 dir)
930 switch (dir) {
931 case DIR8_NORTH:
932 return "n";
933 case DIR8_NORTHEAST:
934 return "ne";
935 case DIR8_EAST:
936 return "e";
937 case DIR8_SOUTHEAST:
938 return "se";
939 case DIR8_SOUTH:
940 return "s";
941 case DIR8_SOUTHWEST:
942 return "sw";
943 case DIR8_WEST:
944 return "w";
945 case DIR8_NORTHWEST:
946 return "nw";
948 log_error("Wrong direction8 variant: %d.", dir);
949 return "";
952 /****************************************************************************
953 Parse a direction name as a direction8.
954 ****************************************************************************/
955 static enum direction8 dir_by_tileset_name(const char *str)
957 enum direction8 dir;
959 for (dir = direction8_begin();
960 dir != direction8_end();
961 dir = direction8_next(dir)) {
962 if (strcmp(dir_get_tileset_name(dir), str) == 0) {
963 return dir;
967 return direction8_invalid();
970 /****************************************************************************
971 Return TRUE iff the dir is valid in this tileset.
972 ****************************************************************************/
973 static bool is_valid_tileset_dir(const struct tileset *t,
974 enum direction8 dir)
976 if (t->hex_width > 0) {
977 return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
978 } else if (t->hex_height > 0) {
979 return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
980 } else {
981 return TRUE;
985 /****************************************************************************
986 Return TRUE iff the dir is cardinal in this tileset.
988 "Cardinal", in this sense, means that a tile will share a border with
989 another tile in the direction rather than sharing just a single vertex.
990 ****************************************************************************/
991 static bool is_cardinal_tileset_dir(const struct tileset *t,
992 enum direction8 dir)
994 if (t->hex_width > 0 || t->hex_height > 0) {
995 return is_valid_tileset_dir(t, dir);
996 } else {
997 return (dir == DIR8_NORTH || dir == DIR8_EAST
998 || dir == DIR8_SOUTH || dir == DIR8_WEST);
1002 /**********************************************************************
1003 Convert properties of the actual topology to an index of different
1004 tileset topology types.
1005 ***********************************************************************/
1006 static int ts_topology_index(int actual_topology)
1008 int idx;
1010 if ((actual_topology & TF_HEX)
1011 && (actual_topology & TF_ISO)) {
1012 idx = TS_TOPO_ISOHEX;
1013 } else if (actual_topology & TF_ISO) {
1014 idx = TS_TOPO_ISO;
1015 } else if (actual_topology & TF_HEX) {
1016 idx = TS_TOPO_HEX;
1017 } else {
1018 idx = TS_TOPO_OVERHEAD;
1021 return idx;
1024 /**********************************************************************
1025 Returns a static list of tilesets available on the system by
1026 searching all data directories for files matching TILESPEC_SUFFIX.
1027 ***********************************************************************/
1028 const struct strvec *get_tileset_list(const struct option *poption)
1030 static struct strvec *tilesets[4] = { NULL, NULL, NULL, NULL };
1031 int topo = option_get_cb_data(poption);
1032 int idx;
1034 idx = ts_topology_index(topo);
1036 fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), NULL);
1038 if (tilesets[idx] == NULL) {
1039 /* Note: this means you must restart the client after installing a new
1040 tileset. */
1041 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1043 tilesets[idx] = strvec_new();
1044 strvec_iterate(list, file) {
1045 struct tileset *t = tileset_read_toplevel(file, FALSE, topo, 1.0f);
1047 if (t) {
1048 strvec_append(tilesets[idx], file);
1049 tileset_free(t);
1051 } strvec_iterate_end;
1052 strvec_destroy(list);
1055 return tilesets[idx];
1058 /**********************************************************************
1059 Gets full filename for tilespec file, based on input name.
1060 Returned data is allocated, and freed by user as required.
1061 Input name may be null, in which case uses default.
1062 Falls back to default if can't find specified name;
1063 dies if can't find default.
1064 ***********************************************************************/
1065 static char *tilespec_fullname(const char *tileset_name)
1067 if (tileset_name) {
1068 char fname[strlen(tileset_name) + strlen(TILESPEC_SUFFIX) + 1];
1069 const char *dname;
1071 fc_snprintf(fname, sizeof(fname),
1072 "%s%s", tileset_name, TILESPEC_SUFFIX);
1074 dname = fileinfoname(get_data_dirs(), fname);
1076 if (dname) {
1077 return fc_strdup(dname);
1081 return NULL;
1084 /**********************************************************************
1085 Checks options in filename match what we require and support.
1086 Die if not.
1087 'which' should be "tilespec" or "spec".
1088 ***********************************************************************/
1089 static bool check_tilespec_capabilities(struct section_file *file,
1090 const char *which,
1091 const char *us_capstr,
1092 const char *filename,
1093 bool verbose)
1095 enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
1097 const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
1099 if (NULL == file_capstr) {
1100 log_base(level, "\"%s\": %s file doesn't have a capability string",
1101 filename, which);
1102 return FALSE;
1104 if (!has_capabilities(us_capstr, file_capstr)) {
1105 log_base(level, "\"%s\": %s file appears incompatible:",
1106 filename, which);
1107 log_base(level, " datafile options: %s", file_capstr);
1108 log_base(level, " supported options: %s", us_capstr);
1109 return FALSE;
1111 if (!has_capabilities(file_capstr, us_capstr)) {
1112 log_base(level, "\"%s\": %s file requires option(s) "
1113 "that client doesn't support:", filename, which);
1114 log_base(level, " datafile options: %s", file_capstr);
1115 log_base(level, " supported options: %s", us_capstr);
1116 return FALSE;
1119 return TRUE;
1122 /**********************************************************************
1123 Frees the tilespec toplevel data, in preparation for re-reading it.
1125 See tilespec_read_toplevel().
1126 ***********************************************************************/
1127 static void tileset_free_toplevel(struct tileset *t)
1129 int i, j;
1131 if (t->main_intro_filename) {
1132 free(t->main_intro_filename);
1133 t->main_intro_filename = NULL;
1136 if (t->preferred_themes) {
1137 for (i = 0; i < t->num_preferred_themes; i++) {
1138 free(t->preferred_themes[i]);
1140 free(t->preferred_themes);
1141 t->preferred_themes = NULL;
1143 t->num_preferred_themes = 0;
1145 if (t->tile_hash) {
1146 drawing_hash_destroy(t->tile_hash);
1147 t->tile_hash = NULL; /* Helpful for sanity. */
1149 if (t->estyle_hash) {
1150 estyle_hash_destroy(t->estyle_hash);
1151 t->estyle_hash = NULL;
1153 for (i = 0; i < ESTYLE_COUNT; i++) {
1154 if (t->style_lists[i] != NULL) {
1155 extra_type_list_destroy(t->style_lists[i]);
1156 t->style_lists[i] = NULL;
1160 if (t->flagged_bases_list != NULL) {
1161 extra_type_list_destroy(t->flagged_bases_list);
1162 t->flagged_bases_list = NULL;
1165 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1166 struct tileset_layer *tslp = &t->layers[i];
1168 if (tslp->match_types) {
1169 for (j = 0; j < tslp->match_count; j++) {
1170 free(tslp->match_types[j]);
1172 free(tslp->match_types);
1173 tslp->match_types = NULL;
1177 if (t->color_system) {
1178 color_system_free(t->color_system);
1179 t->color_system = NULL;
1182 if (t->summary != NULL) {
1183 free(t->summary);
1184 t->summary = NULL;
1186 if (t->description != NULL) {
1187 free(t->description);
1188 t->description = NULL;
1190 if (t->for_ruleset != NULL) {
1191 free(t->for_ruleset);
1192 t->for_ruleset = NULL;
1196 /**************************************************************************
1197 Clean up.
1198 **************************************************************************/
1199 void tileset_free(struct tileset *t)
1201 int i;
1203 tileset_free_tiles(t);
1204 tileset_free_toplevel(t);
1205 for (i = 0; i < ARRAY_SIZE(t->sprites.player); i++) {
1206 tileset_player_free(t, i);
1208 specfile_list_destroy(t->specfiles);
1209 small_sprite_list_destroy(t->small_sprites);
1210 free(t);
1213 /**********************************************************************
1214 Read a new tilespec in when first starting the game.
1216 Call this function with the (guessed) name of the tileset, when
1217 starting the client.
1218 ***********************************************************************/
1219 void tilespec_try_read(const char *tileset_name, bool verbose, int topo_id,
1220 bool global_default)
1222 if (tileset_name == NULL
1223 || !(tileset = tileset_read_toplevel(tileset_name, verbose,
1224 topo_id, 1.0f))) {
1225 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1227 strvec_iterate(list, file) {
1228 struct tileset *t = tileset_read_toplevel(file, FALSE, topo_id, 1.0f);
1230 if (t) {
1231 if (!tileset) {
1232 tileset = t;
1233 } else if (t->priority > tileset->priority
1234 || (topo_id >= 0
1235 && tileset_topo_index(tileset) != tileset_topo_index(t))) {
1236 tileset_free(tileset);
1237 tileset = t;
1238 } else {
1239 tileset_free(t);
1242 } strvec_iterate_end;
1243 strvec_destroy(list);
1245 if (!tileset) {
1246 tileset_error(LOG_FATAL, _("No usable default tileset found, aborting!"));
1249 log_verbose("Trying tileset \"%s\".", tileset->name);
1251 option_set_default_ts(tileset);
1253 if (global_default) {
1254 sz_strlcpy(gui_options.default_tileset_name, tileset_basename(tileset));
1258 /**********************************************************************
1259 Read a new tilespec in from scratch.
1261 Unlike the initial reading code, which reads pieces one at a time,
1262 this gets rid of the old data and reads in the new all at once. If the
1263 new tileset fails to load the old tileset may be reloaded; otherwise the
1264 client will exit. If a NULL name is given the current tileset will be
1265 reread.
1267 It will also call the necessary functions to redraw the graphics.
1268 ***********************************************************************/
1269 void tilespec_reread(const char *new_tileset_name,
1270 bool game_fully_initialized, float scale)
1272 int id;
1273 struct tile *center_tile;
1274 enum client_states state = client_state();
1275 const char *name = new_tileset_name ? new_tileset_name : tileset->name;
1276 char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1278 /* Make local copies since these values may be freed down below */
1279 sz_strlcpy(tileset_name, name);
1280 sz_strlcpy(old_name, tileset->name);
1282 log_normal(_("Loading tileset \"%s\"."), tileset_name);
1284 /* Step 0: Record old data.
1286 * We record the current mapcanvas center, etc.
1288 center_tile = get_center_tile_mapcanvas();
1290 /* Step 1: Cleanup.
1292 * We free all old data in preparation for re-reading it.
1294 tileset_free(tileset);
1296 /* Step 2: Read.
1298 * We read in the new tileset. This should be pretty straightforward.
1300 if (!(tileset = tileset_read_toplevel(tileset_name, FALSE, -1, scale))) {
1301 if (!(tileset = tileset_read_toplevel(old_name, FALSE, -1, scale))) {
1302 /* Always fails. */
1303 fc_assert_exit_msg(NULL != tileset,
1304 "Failed to re-read the currently loaded tileset.");
1307 tileset_load_tiles(tileset);
1308 if (game_fully_initialized) {
1309 tileset_use_preferred_theme(tileset);
1312 if (game_fully_initialized) {
1313 tileset_background_init(tileset);
1314 players_iterate(pplayer) {
1315 tileset_player_init(tileset, pplayer);
1316 } players_iterate_end;
1317 boot_help_texts(); /* "About Current Tileset" */
1320 /* Step 3: Setup
1322 * This is a seriously sticky problem. On startup, we build a hash
1323 * from all the sprite data. Then, when we connect to a server, the
1324 * server sends us ruleset data a piece at a time and we use this data
1325 * to assemble the sprite structures. But if we change while connected
1326 * we have to reassemble all of these. This should just involve
1327 * calling tilespec_setup_*** on everything. But how do we tell what
1328 * "everything" is?
1330 * The below code just does things straightforwardly, by setting up
1331 * each possible sprite again. Hopefully it catches everything, and
1332 * doesn't mess up too badly if we change tilesets while not connected
1333 * to a server.
1335 if (!game.client.ruleset_ready) {
1336 /* The ruleset data is not sent until this point. */
1337 return;
1340 if (!tileset_map_topo_compatible(wld.map.topology_id, tileset)) {
1341 tileset_error(LOG_NORMAL, _("Map topology and tileset incompatible."));
1344 terrain_type_iterate(pterrain) {
1345 tileset_setup_tile_type(tileset, pterrain);
1346 } terrain_type_iterate_end;
1347 unit_type_iterate(punittype) {
1348 tileset_setup_unit_type(tileset, punittype);
1349 } unit_type_iterate_end;
1350 governments_iterate(gov) {
1351 tileset_setup_government(tileset, gov);
1352 } governments_iterate_end;
1353 extra_type_iterate(pextra) {
1354 tileset_setup_extra(tileset, pextra);
1355 } extra_type_iterate_end;
1356 nations_iterate(pnation) {
1357 tileset_setup_nation_flag(tileset, pnation);
1358 } nations_iterate_end;
1359 improvement_iterate(pimprove) {
1360 tileset_setup_impr_type(tileset, pimprove);
1361 } improvement_iterate_end;
1362 advance_iterate(A_FIRST, padvance) {
1363 tileset_setup_tech_type(tileset, padvance);
1364 } advance_iterate_end;
1365 specialist_type_iterate(sp) {
1366 tileset_setup_specialist_type(tileset, sp);
1367 } specialist_type_iterate_end;
1369 for (id = 0; id < game.control.styles_count; id++) {
1370 tileset_setup_city_tiles(tileset, id);
1373 if (state < C_S_RUNNING) {
1374 /* Below redraws do not apply before this. */
1375 return;
1378 /* Step 4: Draw.
1380 * Do any necessary redraws.
1382 generate_citydlg_dimensions();
1383 tileset_changed();
1384 can_slide = FALSE;
1385 center_tile_mapcanvas(center_tile);
1386 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1387 * drawing we might not get one. Of course this is slower. */
1388 update_map_canvas_visible();
1389 can_slide = TRUE;
1392 /**************************************************************************
1393 This is merely a wrapper for tilespec_reread (above) for use in
1394 options.c and the client local options dialog.
1395 **************************************************************************/
1396 void tilespec_reread_callback(struct option *poption)
1398 const char *tileset_name;
1399 enum client_states state = client_state();
1401 if ((state == C_S_RUNNING || state == C_S_OVER)
1402 && option_get_cb_data(poption) != (wld.map.topology_id & (TF_ISO | TF_HEX))) {
1403 /* Changed option was not for current topology */
1404 return;
1407 tileset_name = option_str_get(poption);
1409 /* As it's going to be 'current' tileset, make it global default if
1410 * options saved. */
1411 sz_strlcpy(gui_options.default_tileset_name, tileset_name);
1413 fc_assert_ret(NULL != tileset_name && tileset_name[0] != '\0');
1414 tileset_update = TRUE;
1415 tilespec_reread(tileset_name, client.conn.established, 1.0f);
1416 tileset_update = FALSE;
1417 menus_init();
1420 /**************************************************************************
1422 **************************************************************************/
1423 void tilespec_reread_frozen_refresh(const char *tname)
1425 tileset_update = TRUE;
1426 tilespec_reread(tname, TRUE, 1.0f);
1427 tileset_update = FALSE;
1428 menus_init();
1431 /**************************************************************************
1432 Loads the given graphics file (found in the data path) into a newly
1433 allocated sprite.
1434 **************************************************************************/
1435 static struct sprite *load_gfx_file(const char *gfx_filename)
1437 const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
1438 struct sprite *s;
1440 /* Try out all supported file extensions to find one that works. */
1441 while ((gfx_fileext = *gfx_fileexts++)) {
1442 const char *real_full_name;
1443 char full_name[strlen(gfx_filename) + strlen(".")
1444 + strlen(gfx_fileext) + 1];
1446 sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
1447 if ((real_full_name = fileinfoname(get_data_dirs(), full_name))) {
1448 log_debug("trying to load gfx file \"%s\".", real_full_name);
1449 s = load_gfxfile(real_full_name);
1450 if (s) {
1451 return s;
1456 log_error("Could not load gfx file \"%s\".", gfx_filename);
1457 return NULL;
1460 /**************************************************************************
1461 Ensure that the big sprite of the given spec file is loaded.
1462 **************************************************************************/
1463 static void ensure_big_sprite(struct specfile *sf)
1465 struct section_file *file;
1466 const char *gfx_filename;
1468 if (sf->big_sprite) {
1469 /* Looks like it's already loaded. */
1470 return;
1473 /* Otherwise load it. The big sprite will sometimes be freed and will have
1474 * to be reloaded, but most of the time it's just loaded once, the small
1475 * sprites are extracted, and then it's freed. */
1476 if (!(file = secfile_load(sf->file_name, TRUE))) {
1477 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1480 if (!check_tilespec_capabilities(file, "spec",
1481 SPEC_CAPSTR, sf->file_name, TRUE)) {
1482 tileset_error(LOG_FATAL, _("Incompatible tileset capabilities"));
1485 gfx_filename = secfile_lookup_str(file, "file.gfx");
1487 sf->big_sprite = load_gfx_file(gfx_filename);
1489 if (!sf->big_sprite) {
1490 tileset_error(LOG_FATAL, _("Could not load gfx file for the spec file \"%s\"."),
1491 sf->file_name);
1493 secfile_destroy(file);
1496 /**************************************************************************
1497 Scan all sprites declared in the given specfile. This means that the
1498 positions of the sprites in the big_sprite are saved in the
1499 small_sprite structs.
1500 **************************************************************************/
1501 static void scan_specfile(struct tileset *t, struct specfile *sf,
1502 bool duplicates_ok)
1504 struct section_file *file;
1505 struct section_list *sections;
1506 int i;
1508 if (!(file = secfile_load(sf->file_name, TRUE))) {
1509 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1511 if (!check_tilespec_capabilities(file, "spec",
1512 SPEC_CAPSTR, sf->file_name, TRUE)) {
1513 tileset_error(LOG_FATAL, _("Specfile %s has incompatible capabilities"), sf->file_name);
1516 /* Currently unused */
1517 (void) secfile_entry_lookup(file, "info.artists");
1519 /* Not used here */
1520 (void) secfile_entry_lookup(file, "file.gfx");
1522 if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1523 section_list_iterate(sections, psection) {
1524 int j, k;
1525 int x_top_left, y_top_left, dx, dy;
1526 int pixel_border_x;
1527 int pixel_border_y;
1528 const char *sec_name = section_name(psection);
1530 pixel_border_x = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1531 sec_name);
1532 pixel_border_y = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_y",
1533 sec_name);
1534 pixel_border_x = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_x",
1535 sec_name);
1536 if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1537 || !secfile_lookup_int(file, &y_top_left,
1538 "%s.y_top_left", sec_name)
1539 || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1540 || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1541 log_error("Grid \"%s\" invalid: %s", sec_name, secfile_error());
1542 continue;
1545 j = -1;
1546 while (NULL != secfile_entry_lookup(file, "%s.tiles%d.tag",
1547 sec_name, ++j)) {
1548 struct small_sprite *ss;
1549 int row, column;
1550 int xr, yb;
1551 const char **tags;
1552 size_t num_tags;
1553 int hot_x, hot_y;
1555 if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1556 || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1557 sec_name, j)
1558 || !(tags = secfile_lookup_str_vec(file, &num_tags,
1559 "%s.tiles%d.tag",
1560 sec_name, j))) {
1561 log_error("Small sprite \"%s.tiles%d\" invalid: %s",
1562 sec_name, j, secfile_error());
1563 continue;
1565 hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1566 sec_name, j);
1567 hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1568 sec_name, j);
1570 /* there must be at least 1 because of the while(): */
1571 fc_assert_action(num_tags > 0, continue);
1573 xr = x_top_left + (dx + pixel_border_x) * column;
1574 yb = y_top_left + (dy + pixel_border_y) * row;
1576 ss = fc_malloc(sizeof(*ss));
1577 ss->ref_count = 0;
1578 ss->file = NULL;
1579 ss->x = xr;
1580 ss->y = yb;
1581 ss->width = dx;
1582 ss->height = dy;
1583 ss->sf = sf;
1584 ss->sprite = NULL;
1585 ss->hot_x = hot_x;
1586 ss->hot_y = hot_y;
1588 small_sprite_list_prepend(t->small_sprites, ss);
1590 if (!duplicates_ok) {
1591 for (k = 0; k < num_tags; k++) {
1592 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1593 log_error("warning: already have a sprite for \"%s\".",
1594 tags[k]);
1597 } else {
1598 for (k = 0; k < num_tags; k++) {
1599 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1603 free(tags);
1604 tags = NULL;
1606 } section_list_iterate_end;
1607 section_list_destroy(sections);
1610 /* Load "extra" sprites. Each sprite is one file. */
1611 i = -1;
1612 while (NULL != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1613 struct small_sprite *ss;
1614 const char **tags;
1615 const char *filename;
1616 size_t num_tags, k;
1617 int hot_x, hot_y;
1619 if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1620 "extra.sprites%d.tag", i))
1621 || !(filename = secfile_lookup_str(file,
1622 "extra.sprites%d.file", i))) {
1623 log_error("Extra sprite \"extra.sprites%d\" invalid: %s",
1624 i, secfile_error());
1625 continue;
1627 hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1628 hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1630 ss = fc_malloc(sizeof(*ss));
1631 ss->ref_count = 0;
1632 ss->file = fc_strdup(filename);
1633 ss->sf = NULL;
1634 ss->sprite = NULL;
1635 ss->hot_x = hot_x;
1636 ss->hot_y = hot_y;
1638 small_sprite_list_prepend(t->small_sprites, ss);
1640 if (!duplicates_ok) {
1641 for (k = 0; k < num_tags; k++) {
1642 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1643 log_error("warning: already have a sprite for \"%s\".", tags[k]);
1646 } else {
1647 for (k = 0; k < num_tags; k++) {
1648 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1651 free(tags);
1654 secfile_check_unused(file);
1655 secfile_destroy(file);
1658 /**********************************************************************
1659 Returns the correct name of the gfx file (with path and extension)
1660 Must be free'd when no longer used
1661 ***********************************************************************/
1662 static char *tilespec_gfx_filename(const char *gfx_filename)
1664 const char *gfx_current_fileext;
1665 const char **gfx_fileexts = gfx_fileextensions();
1667 while ((gfx_current_fileext = *gfx_fileexts++)) {
1668 const char *real_full_name;
1669 char *full_name =
1670 fc_malloc(strlen(gfx_filename) + strlen(".")
1671 + strlen(gfx_current_fileext) + 1);
1673 sprintf(full_name, "%s.%s", gfx_filename, gfx_current_fileext);
1675 real_full_name = fileinfoname(get_data_dirs(), full_name);
1676 free(full_name);
1677 if (real_full_name) {
1678 return fc_strdup(real_full_name);
1682 tileset_error(LOG_FATAL, _("Couldn't find a supported gfx file extension for \"%s\"."),
1683 gfx_filename);
1685 return NULL;
1688 /**********************************************************************
1689 Determine the sprite_type string.
1690 ***********************************************************************/
1691 static int check_sprite_type(const char *sprite_type, const char *tile_section)
1693 if (fc_strcasecmp(sprite_type, "corner") == 0) {
1694 return CELL_CORNER;
1696 if (fc_strcasecmp(sprite_type, "single") == 0) {
1697 return CELL_WHOLE;
1699 if (fc_strcasecmp(sprite_type, "whole") == 0) {
1700 return CELL_WHOLE;
1702 log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1703 return CELL_WHOLE;
1706 /**********************************************************************
1707 Finds and reads the toplevel tilespec file based on given name.
1708 Sets global variables, including tile sizes and full names for
1709 intro files.
1710 topology_id of -1 means any topology is acceptable.
1711 ***********************************************************************/
1712 static struct tileset *tileset_read_toplevel(const char *tileset_name,
1713 bool verbose, int topology_id,
1714 float scale)
1716 struct section_file *file;
1717 char *fname;
1718 const char *c;
1719 int i;
1720 size_t num_spec_files;
1721 const char **spec_filenames;
1722 size_t num_layers;
1723 const char **layer_order;
1724 size_t num_preferred_themes;
1725 struct section_list *sections = NULL;
1726 const char *file_capstr;
1727 bool duplicates_ok, is_hex;
1728 enum direction8 dir;
1729 struct tileset *t = NULL;
1730 const char *extraname;
1731 const char *tstr;
1732 int topo;
1734 fname = tilespec_fullname(tileset_name);
1735 if (!fname) {
1736 if (verbose) {
1737 log_error("Can't find tileset \"%s\".", tileset_name);
1739 return NULL;
1741 log_verbose("tilespec file is \"%s\".", fname);
1743 if (!(file = secfile_load(fname, TRUE))) {
1744 log_error("Could not open '%s':\n%s", fname, secfile_error());
1745 free(fname);
1746 return NULL;
1749 if (!check_tilespec_capabilities(file, "tilespec",
1750 TILESPEC_CAPSTR, fname, verbose)) {
1751 secfile_destroy(file);
1752 free(fname);
1753 return NULL;
1756 t = tileset_new();
1757 t->scale = scale;
1758 file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1759 duplicates_ok = (NULL != file_capstr
1760 && has_capabilities("+duplicates_ok", file_capstr));
1762 tstr = secfile_lookup_str(file, "tilespec.name");
1763 /* Tileset name found */
1764 sz_strlcpy(t->given_name, tstr);
1765 tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1766 if (tstr[0] != '\0') {
1767 /* Tileset version found */
1768 sz_strlcpy(t->version, tstr);
1769 } else {
1770 /* No version information */
1771 t->version[0] = '\0';
1774 tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
1775 if (tstr[0] != '\0') {
1776 int len;
1778 /* Tileset summary found */
1779 len = strlen(tstr);
1780 t->summary = fc_malloc(len + 1);
1781 fc_strlcpy(t->summary, tstr, len + 1);
1782 } else {
1783 /* No summary */
1784 if (t->summary != NULL) {
1785 free(t->summary);
1786 t->summary = NULL;
1790 tstr = secfile_lookup_str_default(file, "", "tilespec.description");
1791 if (tstr[0] != '\0') {
1792 int len;
1794 /* Tileset description found */
1795 len = strlen(tstr);
1796 t->description = fc_malloc(len + 1);
1797 fc_strlcpy(t->description, tstr, len + 1);
1798 } else {
1799 /* No description */
1800 if (t->description != NULL) {
1801 free(t->description);
1802 t->description = NULL;
1806 tstr = secfile_lookup_str_default(file, NULL, "tilespec.for_ruleset");
1807 if (tstr != NULL) {
1808 t->for_ruleset = fc_strdup(tstr);
1809 } else {
1810 t->for_ruleset = NULL;
1813 sz_strlcpy(t->name, tileset_name);
1814 if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1815 || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1816 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1817 goto ON_ERROR;
1820 tstr = secfile_lookup_str(file, "tilespec.type");
1821 if (tstr == NULL) {
1822 log_error("Tileset \"%s\": no tileset type", t->name);
1823 goto ON_ERROR;
1826 t->type = ts_type_by_name(tstr, fc_strcasecmp);
1827 if (!ts_type_is_valid(t->type)) {
1828 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1829 goto ON_ERROR;
1832 if (t->type == TS_ISOMETRIC) {
1833 topo = TF_ISO;
1834 } else {
1835 topo = 0;
1838 if (t->type == TS_ISOMETRIC) {
1839 topo = TF_ISO;
1840 } else {
1841 topo = 0;
1844 /* Read hex-tileset information. */
1845 t->hex_width = t->hex_height = 0;
1846 if (is_hex) {
1847 int hex_side;
1849 if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1850 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1851 goto ON_ERROR;
1853 hex_side = hex_side * t->scale;
1854 if (t->type == TS_ISOMETRIC) {
1855 t->hex_width = hex_side;
1856 } else {
1857 t->hex_height = hex_side;
1860 topo |= TF_HEX;
1862 /* Hex tilesets are drawn the same as isometric. */
1863 /* FIXME: There will be other legal values to be used with hex
1864 * tileset in the future, and this would just overwrite it. */
1865 t->type = TS_ISOMETRIC;
1868 if (topology_id >= 0 && topo != (topology_id & (TF_ISO | TF_HEX))) {
1869 /* Not of requested topology */
1870 goto ON_ERROR;
1873 t->ts_topo_idx = ts_topology_index(topo);
1875 if (!is_view_supported(t->type)) {
1876 log_normal(_("Client does not support %s tilesets."),
1877 _(ts_type_name(t->type)));
1878 log_normal(_("Using default tileset instead."));
1879 fc_assert(tileset_name != NULL);
1880 goto ON_ERROR;
1883 /* Create arrays of valid and cardinal tileset dirs. These depend
1884 * entirely on the tileset, not the topology. They are also in clockwise
1885 * rotational ordering. */
1886 t->num_valid_tileset_dirs = t->num_cardinal_tileset_dirs = 0;
1887 dir = DIR8_NORTH;
1888 do {
1889 if (is_valid_tileset_dir(t, dir)) {
1890 t->valid_tileset_dirs[t->num_valid_tileset_dirs] = dir;
1891 t->num_valid_tileset_dirs++;
1893 if (is_cardinal_tileset_dir(t, dir)) {
1894 t->cardinal_tileset_dirs[t->num_cardinal_tileset_dirs] = dir;
1895 t->num_cardinal_tileset_dirs++;
1898 dir = dir_cw(dir);
1899 } while (dir != DIR8_NORTH);
1900 fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
1901 t->num_index_valid = 1 << t->num_valid_tileset_dirs;
1902 t->num_index_cardinal = 1 << t->num_cardinal_tileset_dirs;
1904 if (!secfile_lookup_int(file, &t->normal_tile_width,
1905 "tilespec.normal_tile_width")
1906 || !secfile_lookup_int(file, &t->normal_tile_height,
1907 "tilespec.normal_tile_height")) {
1908 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1909 goto ON_ERROR;
1911 t->normal_tile_width = ceil(t->scale * t->normal_tile_width);
1912 // Adjust width to be multiple of 8
1913 if (scale != 1.0f) {
1914 i = t->normal_tile_width;
1915 while (i % 8 != 0) {
1916 i++;
1918 t->scale = (t->scale * i) / t->normal_tile_width;
1919 t->normal_tile_width = i;
1921 t->normal_tile_height = ceil(t->scale * t->normal_tile_height);
1922 if (t->type == TS_ISOMETRIC) {
1923 t->full_tile_width = t->normal_tile_width;
1924 if (tileset_hex_height(t) > 0) {
1925 t->full_tile_height = t->normal_tile_height;
1926 } else {
1927 t->full_tile_height = 3 * t->normal_tile_height / 2;
1929 } else {
1930 t->full_tile_width = t->normal_tile_width;
1931 t->full_tile_height = t->normal_tile_height;
1933 t->unit_tile_width
1934 = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
1935 t->unit_tile_height
1936 = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
1937 if (!secfile_lookup_int(file, &t->small_sprite_width,
1938 "tilespec.small_tile_width")
1939 || !secfile_lookup_int(file, &t->small_sprite_height,
1940 "tilespec.small_tile_height")) {
1941 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1942 goto ON_ERROR;
1944 if (t->unit_tile_width != t->full_tile_width && t->scale != 1.0f) {
1945 t->unit_tile_width = ceil(t->unit_tile_width * t->scale);
1947 if (t->unit_tile_height != t->full_tile_height && t->scale != 1.0f) {
1948 t->unit_tile_height = ceil(t->unit_tile_height * t->scale);
1950 t->small_sprite_width = t->small_sprite_width * t->scale;
1951 t->small_sprite_height = t->small_sprite_height * t->scale;
1952 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1953 t->normal_tile_width, t->normal_tile_height,
1954 t->full_tile_width, t->full_tile_height,
1955 t->small_sprite_width, t->small_sprite_height);
1957 tstr = secfile_lookup_str(file, "tilespec.fog_style");
1958 if (tstr == NULL) {
1959 log_error("Tileset \"%s\": no fog_style", t->name);
1960 goto ON_ERROR;
1963 t->fogstyle = fog_style_by_name(tstr, fc_strcasecmp);
1964 if (!fog_style_is_valid(t->fogstyle)) {
1965 log_error("Tileset \"%s\": unknown fog_style \"%s\"", t->name, tstr);
1966 goto ON_ERROR;
1969 tstr = secfile_lookup_str(file, "tilespec.darkness_style");
1970 if (tstr == NULL) {
1971 log_error("Tileset \"%s\": no darkness_style", t->name);
1972 goto ON_ERROR;
1975 t->darkness_style = darkness_style_by_name(tstr, fc_strcasecmp);
1976 if (!darkness_style_is_valid(t->darkness_style)) {
1977 log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t->name, tstr);
1978 goto ON_ERROR;
1981 if (t->darkness_style == DARKNESS_ISORECT
1982 && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
1983 log_error("Invalid darkness style set in tileset \"%s\".", t->name);
1984 goto ON_ERROR;
1987 if (!secfile_lookup_int(file, &t->unit_flag_offset_x,
1988 "tilespec.unit_flag_offset_x")
1989 || !secfile_lookup_int(file, &t->unit_flag_offset_y,
1990 "tilespec.unit_flag_offset_y")
1991 || !secfile_lookup_int(file, &t->city_flag_offset_x,
1992 "tilespec.city_flag_offset_x")
1993 || !secfile_lookup_int(file, &t->city_flag_offset_y,
1994 "tilespec.city_flag_offset_y")
1995 || !secfile_lookup_int(file, &t->unit_offset_x,
1996 "tilespec.unit_offset_x")
1997 || !secfile_lookup_int(file, &t->unit_offset_y,
1998 "tilespec.unit_offset_y")
1999 || !secfile_lookup_int(file, &t->activity_offset_x,
2000 "tilespec.activity_offset_x")
2001 || !secfile_lookup_int(file, &t->activity_offset_y,
2002 "tilespec.activity_offset_y")
2003 || !secfile_lookup_int(file, &t->select_offset_x,
2004 "tilespec.select_offset_x")
2005 || !secfile_lookup_int(file, &t->select_offset_y,
2006 "tilespec.select_offset_y")
2007 || !secfile_lookup_int(file, &t->city_offset_x,
2008 "tilespec.city_offset_x")
2009 || !secfile_lookup_int(file, &t->city_offset_y,
2010 "tilespec.city_offset_y")
2011 || !secfile_lookup_int(file, &t->city_size_offset_x,
2012 "tilespec.city_size_offset_x")
2013 || !secfile_lookup_int(file, &t->city_size_offset_y,
2014 "tilespec.city_size_offset_y")
2015 || !secfile_lookup_int(file, &t->citybar_offset_y,
2016 "tilespec.citybar_offset_y")
2017 || !secfile_lookup_int(file, &t->tilelabel_offset_y,
2018 "tilespec.tilelabel_offset_y")
2019 || !secfile_lookup_int(file, &t->occupied_offset_x,
2020 "tilespec.occupied_offset_x")
2021 || !secfile_lookup_int(file, &t->occupied_offset_y,
2022 "tilespec.occupied_offset_y")
2023 || !secfile_lookup_int(file, &t->city_names_font_size,
2024 "tilespec.city_names_font_size")
2025 || !secfile_lookup_int(file, &t->city_productions_font_size,
2026 "tilespec.city_productions_font_size")) {
2027 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2028 goto ON_ERROR;
2031 t->unit_upkeep_offset_y = secfile_lookup_int_default(file, tileset_tile_height(t),
2032 "tilespec.unit_upkeep_offset_y");
2033 t->unit_upkeep_small_offset_y = secfile_lookup_int_default(file, t->unit_upkeep_offset_y,
2034 "tilespec.unit_upkeep_small_offset_y");
2035 t->unit_flag_offset_x = t->scale * t->unit_flag_offset_x;
2036 t->unit_flag_offset_y = t->scale * t->unit_flag_offset_y;
2037 t->city_flag_offset_x = t->scale * t->city_flag_offset_x;
2038 t->city_flag_offset_y = t->scale * t->city_flag_offset_y;
2039 t->unit_offset_x = t->scale * t->unit_offset_x;
2040 t->unit_offset_y = t->scale * t->unit_offset_y;
2041 t->activity_offset_x = t->scale * t->activity_offset_x;
2042 t->activity_offset_y = t->scale * t->activity_offset_y;
2043 t->city_offset_x = t->scale * t->city_offset_x;
2044 t->city_offset_y = t->scale * t->city_offset_y;
2045 t->citybar_offset_y = t->scale * t->citybar_offset_y;
2046 t->tilelabel_offset_y = t->scale * t->tilelabel_offset_y;
2047 t->occupied_offset_x = t->scale * t->occupied_offset_x;
2048 t->occupied_offset_y = t->scale * t->occupied_offset_y;
2049 if (t->scale != 1.0f
2050 && t->unit_upkeep_offset_y != tileset_tile_height(t)) {
2051 t->unit_upkeep_offset_y = t->scale * t->unit_upkeep_offset_y;
2053 if (t->scale != 1.0f
2054 && t->unit_upkeep_small_offset_y != t->unit_upkeep_offset_y) {
2055 t->unit_upkeep_small_offset_y = t->scale * t->unit_upkeep_small_offset_y;
2058 set_city_names_font_sizes(t->city_names_font_size,
2059 t->city_productions_font_size);
2061 c = secfile_lookup_str_default(file, NULL,
2062 "tilespec.unit_default_orientation");
2063 if (!c) {
2064 /* This is valid, but tileset must specify icon for every unit */
2065 t->unit_default_orientation = direction8_invalid();
2066 } else {
2067 dir = dir_by_tileset_name(c);
2069 if (!direction8_is_valid(dir)) {
2070 tileset_error(LOG_ERROR, "Tileset \"%s\": unknown "
2071 "unit_default_orientation \"%s\"", t->name, c);
2072 goto ON_ERROR;
2073 } else {
2074 /* Default orientation is allowed to not be a valid one for the
2075 * tileset */
2076 t->unit_default_orientation = dir;
2080 c = secfile_lookup_str(file, "tilespec.main_intro_file");
2081 t->main_intro_filename = tilespec_gfx_filename(c);
2082 log_debug("intro file %s", t->main_intro_filename);
2084 /* Layer order */
2085 num_layers = 0;
2086 layer_order = secfile_lookup_str_vec(file, &num_layers,
2087 "tilespec.layer_order");
2088 if (layer_order != NULL) {
2089 for (i = 0; i < num_layers; i++) {
2090 int j;
2091 enum mapview_layer layer = mapview_layer_by_name(layer_order[i],
2092 fc_strcasecmp);
2094 /* Check for wrong layer names. */
2095 if (!mapview_layer_is_valid(layer)) {
2096 log_error("layer_order: Invalid layer \"%s\"", layer_order[i]);
2097 goto ON_ERROR;
2099 /* Check for duplicates. */
2100 for (j = 0; j < i; j++) {
2101 if (t->layer_order[j] == layer) {
2102 log_error("layer_order: Duplicate layer \"%s\"", layer_order[i]);
2103 goto ON_ERROR;
2106 t->layer_order[i] = layer;
2109 /* Now check that all layers are present. Doing it now allows for a more
2110 * comprehensive error message. */
2111 for (i = 0; i < LAYER_COUNT; i++) {
2112 int j;
2113 bool found = FALSE;
2115 for (j = 0; j < num_layers; j++) {
2116 if (i == t->layer_order[j]) {
2117 found = TRUE;
2118 break;
2121 if (!found) {
2122 log_error("layer_order: Missing layer \"%s\"",
2123 mapview_layer_name(i));
2124 goto ON_ERROR;
2127 } else {
2128 /* There is no layer_order tag in the specfile -> use the default */
2129 for (i = 0; i < LAYER_COUNT; i++) {
2130 t->layer_order[i] = i;
2134 /* Terrain layer info. */
2135 for (i = 0; i < MAX_NUM_LAYERS; i++) {
2136 struct tileset_layer *tslp = &t->layers[i];
2137 int j, k;
2139 tslp->match_types =
2140 (char **) secfile_lookup_str_vec(file, &tslp->match_count,
2141 "layer%d.match_types", i);
2142 for (j = 0; j < tslp->match_count; j++) {
2143 tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
2145 for (k = 0; k < j; k++) {
2146 if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
2147 tileset_error(LOG_FATAL, _("[layer%d] match_types: \"%s\" initial "
2148 "('%c') is not unique."),
2149 i, tslp->match_types[j], tslp->match_types[j][0]);
2150 /* FIXME: Returns NULL. */
2156 /* Tile drawing info. */
2157 sections = secfile_sections_by_name_prefix(file, TILE_SECTION_PREFIX);
2158 if (NULL == sections || 0 == section_list_size(sections)) {
2159 tileset_error(LOG_ERROR, _("No [%s] sections supported by tileset \"%s\"."),
2160 TILE_SECTION_PREFIX, fname);
2161 goto ON_ERROR;
2164 fc_assert(t->tile_hash == NULL);
2165 t->tile_hash = drawing_hash_new();
2167 section_list_iterate(sections, psection) {
2168 const char *sec_name = section_name(psection);
2169 struct drawing_data *draw = drawing_data_new();
2170 const char *sprite_type;
2171 int l;
2172 const char *terrain_name;
2174 terrain_name = secfile_lookup_str(file, "%s.tag", sec_name);
2176 if (terrain_name != NULL) {
2177 draw->name = fc_strdup(terrain_name);
2178 } else {
2179 tileset_error(LOG_ERROR, _("No terrain tag given in section [%s]."), sec_name);
2180 drawing_data_destroy(draw);
2181 goto ON_ERROR;
2184 draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
2185 sec_name);
2186 draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
2188 draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
2189 "%s.is_reversed",
2190 sec_name);
2191 draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
2192 sec_name);
2193 draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
2195 for (l = 0; l < draw->num_layers; l++) {
2196 struct drawing_layer *dlp = &draw->layer[l];
2197 struct tileset_layer *tslp = &t->layers[l];
2198 const char *match_type;
2199 const char **match_with;
2200 size_t count;
2202 dlp->is_tall
2203 = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
2204 sec_name, l);
2205 dlp->offset_x
2206 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
2207 sec_name, l);
2208 dlp->offset_y
2209 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
2210 sec_name, l);
2211 dlp->offset_x = ceil(t->scale * dlp->offset_x);
2212 dlp->offset_y = ceil(t->scale * dlp->offset_y);
2214 match_type = secfile_lookup_str_default(file, NULL,
2215 "%s.layer%d_match_type",
2216 sec_name, l);
2217 if (match_type) {
2218 int j;
2220 /* Determine our match_type. */
2221 for (j = 0; j < tslp->match_count; j++) {
2222 if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
2223 break;
2226 if (j >= tslp->match_count) {
2227 log_error("[%s] invalid match_type \"%s\".", sec_name, match_type);
2228 } else {
2229 dlp->match_index[dlp->match_indices++] = j;
2233 match_with = secfile_lookup_str_vec(file, &count,
2234 "%s.layer%d_match_with",
2235 sec_name, l);
2236 if (match_with) {
2237 int j, k;
2239 if (count > MAX_NUM_MATCH_WITH) {
2240 log_error("[%s] match_with has too many types (%d, max %d)",
2241 sec_name, (int) count, MAX_NUM_MATCH_WITH);
2242 count = MAX_NUM_MATCH_WITH;
2245 if (1 < dlp->match_indices) {
2246 log_error("[%s] previous match_with ignored.", sec_name);
2247 dlp->match_indices = 1;
2248 } else if (1 > dlp->match_indices) {
2249 log_error("[%s] missing match_type, using \"%s\".",
2250 sec_name, tslp->match_types[0]);
2251 dlp->match_index[0] = 0;
2252 dlp->match_indices = 1;
2255 for (k = 0; k < count; k++) {
2256 for (j = 0; j < tslp->match_count; j++) {
2257 if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
2258 break;
2261 if (j >= tslp->match_count) {
2262 log_error("[%s] layer%d_match_with: invalid \"%s\".",
2263 sec_name, l, match_with[k]);
2264 } else if (1 < count) {
2265 int m;
2267 for (m = 0; m < dlp->match_indices; m++) {
2268 if (dlp->match_index[m] == j) {
2269 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
2270 sec_name, l, match_with[k]);
2271 break;
2274 if (m >= dlp->match_indices) {
2275 dlp->match_index[dlp->match_indices++] = j;
2277 } else {
2278 dlp->match_index[dlp->match_indices++] = j;
2281 free(match_with);
2282 match_with = NULL;
2285 /* Check match_indices */
2286 switch (dlp->match_indices) {
2287 case 0:
2288 case 1:
2289 dlp->match_style = MATCH_NONE;
2290 break;
2291 case 2:
2292 if (dlp->match_index[0] == dlp->match_index[1] ) {
2293 dlp->match_style = MATCH_SAME;
2294 } else {
2295 dlp->match_style = MATCH_PAIR;
2297 break;
2298 default:
2299 dlp->match_style = MATCH_FULL;
2300 break;
2303 sprite_type
2304 = secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
2305 sec_name, l);
2306 dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
2308 switch (dlp->sprite_type) {
2309 case CELL_WHOLE:
2310 /* OK, no problem */
2311 break;
2312 case CELL_CORNER:
2313 if (dlp->is_tall
2314 || dlp->offset_x > 0
2315 || dlp->offset_y > 0) {
2316 log_error("[%s] layer %d: you cannot have tall terrain or\n"
2317 "a sprite offset with a cell-based drawing method.",
2318 sec_name, l);
2319 dlp->is_tall = FALSE;
2320 dlp->offset_x = dlp->offset_y = 0;
2322 break;
2326 if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
2327 log_error("warning: multiple tile sections containing terrain tag \"%s\".",
2328 draw->name);
2329 goto ON_ERROR;
2331 } section_list_iterate_end;
2332 section_list_destroy(sections);
2333 sections = NULL;
2335 t->estyle_hash = estyle_hash_new();
2337 for (i = 0; i < ESTYLE_COUNT; i++) {
2338 t->style_lists[i] = extra_type_list_new();
2340 t->flagged_bases_list = extra_type_list_new();
2342 for (i = 0; (extraname = secfile_lookup_str_default(file, NULL,
2343 "extras.styles%d.name",
2344 i)); i++) {
2345 const char *style_name;
2346 enum extrastyle_id style;
2348 style_name = secfile_lookup_str_default(file, "Single1",
2349 "extras.styles%d.style", i);
2350 style = extrastyle_id_by_name(style_name, fc_strcasecmp);
2351 if (!extrastyle_id_is_valid(style)) {
2352 log_error("Unknown extra style \"%s\" for road \"%s\"",
2353 style_name, extraname);
2354 goto ON_ERROR;
2357 if (!estyle_hash_insert(t->estyle_hash, extraname, style)) {
2358 log_error("warning: duplicate extrastyle entry [%s].", extraname);
2359 goto ON_ERROR;
2363 spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
2364 "tilespec.files");
2365 if (NULL == spec_filenames || 0 == num_spec_files) {
2366 log_error("No tile graphics files specified in \"%s\"", fname);
2367 goto ON_ERROR;
2370 fc_assert(t->sprite_hash == NULL);
2371 t->sprite_hash = sprite_hash_new();
2372 for (i = 0; i < num_spec_files; i++) {
2373 struct specfile *sf = fc_malloc(sizeof(*sf));
2374 const char *dname;
2376 log_debug("spec file %s", spec_filenames[i]);
2378 sf->big_sprite = NULL;
2379 dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
2380 if (!dname) {
2381 if (verbose) {
2382 log_error("Can't find spec file \"%s\".", spec_filenames[i]);
2384 goto ON_ERROR;
2386 sf->file_name = fc_strdup(dname);
2387 scan_specfile(t, sf, duplicates_ok);
2389 specfile_list_prepend(t->specfiles, sf);
2391 free(spec_filenames);
2393 t->color_system = color_system_read(file);
2395 /* FIXME: remove this hack. */
2396 t->preferred_themes =
2397 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2398 "tilespec.preferred_themes");
2399 if (num_preferred_themes <= 0) {
2400 t->preferred_themes =
2401 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2402 "tilespec.prefered_themes");
2403 if (num_preferred_themes > 0) {
2404 log_deprecation("Entry tilespec.prefered_themes in tilespec."
2405 " Use correct spelling tilespec.preferred_themes instead");
2408 t->num_preferred_themes = num_preferred_themes;
2409 for (i = 0; i < t->num_preferred_themes; i++) {
2410 t->preferred_themes[i] = fc_strdup(t->preferred_themes[i]);
2413 secfile_check_unused(file);
2414 secfile_destroy(file);
2415 log_verbose("finished reading \"%s\".", fname);
2416 free(fname);
2418 return t;
2420 ON_ERROR:
2421 secfile_destroy(file);
2422 free(fname);
2423 tileset_free(t);
2424 if (NULL != sections) {
2425 section_list_destroy(sections);
2427 return NULL;
2430 /**********************************************************************
2431 Returns a text name for the citizen, as used in the tileset.
2432 ***********************************************************************/
2433 static const char *citizen_rule_name(enum citizen_category citizen)
2435 /* These strings are used in reading the tileset. Do not
2436 * translate. */
2437 switch (citizen) {
2438 case CITIZEN_HAPPY:
2439 return "happy";
2440 case CITIZEN_CONTENT:
2441 return "content";
2442 case CITIZEN_UNHAPPY:
2443 return "unhappy";
2444 case CITIZEN_ANGRY:
2445 return "angry";
2446 default:
2447 break;
2449 log_error("Unknown citizen type: %d.", (int) citizen);
2450 return NULL;
2453 /****************************************************************************
2454 Return a directional string for the cardinal directions. Normally the
2455 binary value 1000 will be converted into "n1e0s0w0". This is in a
2456 clockwise ordering.
2457 ****************************************************************************/
2458 static const char *cardinal_index_str(const struct tileset *t, int idx)
2460 static char c[64];
2461 int i;
2463 c[0] = '\0';
2464 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2465 int value = (idx >> i) & 1;
2467 cat_snprintf(c, sizeof(c), "%s%d",
2468 dir_get_tileset_name(t->cardinal_tileset_dirs[i]), value);
2471 return c;
2474 /****************************************************************************
2475 Do the same thing as cardinal_str, except including all valid directions.
2476 The returned string is a pointer to static memory.
2477 ****************************************************************************/
2478 static char *valid_index_str(const struct tileset *t, int idx)
2480 static char c[64];
2481 int i;
2483 c[0] = '\0';
2484 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2485 int value = (idx >> i) & 1;
2487 cat_snprintf(c, sizeof(c), "%s%d",
2488 dir_get_tileset_name(t->valid_tileset_dirs[i]), value);
2491 return c;
2494 /**************************************************************************
2495 Loads the sprite. If the sprite is already loaded a reference
2496 counter is increased. Can return NULL if the sprite couldn't be
2497 loaded.
2498 Scale means if sprite should be scaled, smooth if scaling might use
2499 other scaling algorithm than nearest neighbor.
2500 **************************************************************************/
2501 static struct sprite *load_sprite(struct tileset *t, const char *tag_name,
2502 bool scale, bool smooth)
2504 struct small_sprite *ss;
2505 float sprite_scale = 1.0f;
2507 log_debug("load_sprite(tag='%s')", tag_name);
2508 /* Lookup information about where the sprite is found. */
2509 if (!sprite_hash_lookup(t->sprite_hash, tag_name, &ss)) {
2510 return NULL;
2513 fc_assert(ss->ref_count >= 0);
2515 if (!ss->sprite) {
2516 /* If the sprite hasn't been loaded already, then load it. */
2517 fc_assert(ss->ref_count == 0);
2518 if (ss->file) {
2519 int w, h;
2520 struct sprite *s;
2522 if (scale) {
2523 s = load_gfx_file(ss->file);
2524 get_sprite_dimensions(s, &w, &h);
2525 ss->sprite = crop_sprite(s, 0, 0, w,
2526 h, NULL, -1, -1, t->scale, smooth);
2527 free_sprite(s);
2528 } else {
2529 ss->sprite = load_gfx_file(ss->file);
2531 if (!ss->sprite) {
2532 tileset_error(LOG_FATAL, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2533 ss->file, tag_name);
2535 } else {
2536 int sf_w, sf_h;
2538 ensure_big_sprite(ss->sf);
2539 get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2540 if (ss->x < 0 || ss->x + ss->width > sf_w
2541 || ss->y < 0 || ss->y + ss->height > sf_h) {
2542 tileset_error(LOG_ERROR, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2543 tag_name, ss->sf->file_name);
2544 return NULL;
2546 if (scale) {
2547 sprite_scale = t->scale;
2549 ss->sprite = crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width,
2550 ss->height, NULL, -1, -1, sprite_scale,
2551 smooth);
2555 /* Track the reference count so we know when to free the sprite. */
2556 ss->ref_count++;
2558 return ss->sprite;
2561 /**************************************************************************
2562 Create a sprite with the given color and tag.
2563 **************************************************************************/
2564 static struct sprite *create_plr_sprite(struct color *pcolor)
2566 struct sprite *sprite;
2568 fc_assert_ret_val(pcolor != NULL, NULL);
2570 sprite = create_sprite(128, 64, pcolor);
2572 return sprite;
2575 /**************************************************************************
2576 Unloads the sprite. Decrease the reference counter. If the last
2577 reference is removed the sprite is freed.
2578 **************************************************************************/
2579 static void unload_sprite(struct tileset *t, const char *tag_name)
2581 struct small_sprite *ss;
2583 sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
2584 fc_assert_ret(ss);
2585 fc_assert_ret(ss->ref_count >= 1);
2586 fc_assert_ret(ss->sprite);
2588 ss->ref_count--;
2590 if (ss->ref_count == 0) {
2591 /* Nobody's using the sprite anymore, so we should free it. We know
2592 * where to find it if we need it again. */
2593 log_debug("freeing sprite '%s'.", tag_name);
2594 free_sprite(ss->sprite);
2595 ss->sprite = NULL;
2599 /**************************************************************************
2600 Return TRUE iff the specified sprite exists in the tileset (whether
2601 or not it is currently loaded).
2602 **************************************************************************/
2603 static bool sprite_exists(const struct tileset *t, const char *tag_name)
2605 /* Lookup information about where the sprite is found. */
2606 return sprite_hash_lookup(t->sprite_hash, tag_name, NULL);
2609 /* Not very safe, but convenient: */
2610 #define SET_SPRITE(field, tag) \
2611 do { \
2612 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2613 if (t->sprites.field == NULL) { \
2614 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2616 } while (FALSE)
2619 #define SET_SPRITE_NOTSMOOTH(field, tag) \
2620 do { \
2621 t->sprites.field = load_sprite(t, tag, TRUE, FALSE); \
2622 if (t->sprites.field == NULL) { \
2623 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2625 } while (FALSE)
2627 #define SET_SPRITE_UNSCALED(field, tag) \
2628 do { \
2629 t->sprites.field = load_sprite(t, tag, FALSE, FALSE); \
2630 if (t->sprites.field == NULL) { \
2631 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2633 } while (FALSE)
2635 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2636 #define SET_SPRITE_ALT(field, tag, alt) \
2637 do { \
2638 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2639 if (!t->sprites.field) { \
2640 t->sprites.field = load_sprite(t, alt, TRUE, TRUE); \
2642 if (t->sprites.field == NULL) { \
2643 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are " \
2644 "both missing."), tag, alt); \
2646 } while (FALSE)
2648 /* Sets sprites.field to tag, or NULL if not available */
2649 #define SET_SPRITE_OPT(field, tag) \
2650 t->sprites.field = load_sprite(t, tag, TRUE, TRUE)
2652 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2653 do { \
2654 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2655 "sprite", #field, TRUE); \
2656 } while (FALSE)
2658 /****************************************************************************
2659 Setup the graphics for specialist types.
2660 ****************************************************************************/
2661 void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
2663 /* Load the specialist sprite graphics. */
2664 char buffer[512];
2665 int j;
2666 const char *name = specialist_rule_name(specialist_by_number(id));
2667 const char *graphic_alt = specialist_by_number(id)->graphic_alt;
2669 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2670 /* Try rule name + index number */
2671 fc_snprintf(buffer, sizeof(buffer), "specialist.%s_%d", name, j);
2672 t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer, FALSE,
2673 FALSE);
2675 /* Break if no more index specific sprites are defined */
2676 if (!t->sprites.specialist[id].sprite[j]) {
2677 break;
2681 /* Nothing? Try the alt tag */
2682 if (j == 0) {
2683 t->sprites.specialist[id].sprite[j] = load_sprite(t, graphic_alt, FALSE,
2684 FALSE);
2686 if (t->sprites.specialist[id].sprite[j]) {
2687 j = 1;
2691 t->sprites.specialist[id].count = j;
2693 /* Still nothing? Give up. */
2694 if (j == 0) {
2695 tileset_error(LOG_FATAL, _("No graphics for specialist \"%s\"."), name);
2699 /****************************************************************************
2700 Setup the graphics for (non-specialist) citizen types.
2701 ****************************************************************************/
2702 static void tileset_setup_citizen_types(struct tileset *t)
2704 int i, j;
2705 char buffer[512];
2707 /* Load the citizen sprite graphics, no specialist. */
2708 for (i = 0; i < CITIZEN_LAST; i++) {
2709 const char *name = citizen_rule_name(i);
2711 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2712 fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
2713 t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer, FALSE, FALSE);
2714 if (!t->sprites.citizen[i].sprite[j]) {
2715 break;
2718 t->sprites.citizen[i].count = j;
2719 if (j == 0) {
2720 tileset_error(LOG_FATAL, _("No graphics for citizen \"%s\"."), name);
2725 /****************************************************************************
2726 Return the sprite in the city_sprite listing that corresponds to this
2727 city - based on city style and size.
2729 See also load_city_sprite, free_city_sprite.
2730 ****************************************************************************/
2731 static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
2732 const struct city *pcity)
2734 /* get style and match the best tile based on city size */
2735 int style = style_of_city(pcity);
2736 int num_thresholds;
2737 struct city_style_threshold *thresholds;
2738 int img_index;
2740 fc_assert_ret_val(style < city_sprite->num_styles, NULL);
2742 num_thresholds = city_sprite->styles[style].land_num_thresholds;
2743 thresholds = city_sprite->styles[style].land_thresholds;
2745 if (num_thresholds == 0) {
2746 return NULL;
2749 /* Get the sprite with the index defined by the effects. */
2750 img_index = pcity->client.city_image;
2751 if (img_index == -100) {
2752 /* Server doesn't know right value as this is from old savegame.
2753 * Guess here based on *client* side information as was done in
2754 * versions where information was not saved to savegame - this should
2755 * give us right answer of what city looked like by the time it was
2756 * put under FoW. */
2757 img_index = get_city_bonus(pcity, EFT_CITY_IMAGE);
2759 img_index = CLIP(0, img_index, num_thresholds - 1);
2761 return thresholds[img_index].sprite;
2764 /****************************************************************************
2765 Allocates one threshold set for city sprite
2766 ****************************************************************************/
2767 static int load_city_thresholds_sprites(struct tileset *t, const char *tag,
2768 char *graphic, char *graphic_alt,
2769 struct city_style_threshold **thresholds)
2771 char buffer[128];
2772 char *gfx_in_use = graphic;
2773 int num_thresholds = 0;
2774 struct sprite *sprite;
2775 int size;
2777 *thresholds = NULL;
2779 for (size = 0; size < MAX_CITY_SIZE; size++) {
2780 fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
2781 gfx_in_use, tag, size);
2782 if ((sprite = load_sprite(t, buffer, TRUE, TRUE))) {
2783 num_thresholds++;
2784 *thresholds = fc_realloc(*thresholds, num_thresholds * sizeof(**thresholds));
2785 (*thresholds)[num_thresholds - 1].sprite = sprite;
2786 } else if (size == 0) {
2787 if (gfx_in_use == graphic) {
2788 /* Try again with graphic_alt. */
2789 size--;
2790 gfx_in_use = graphic_alt;
2791 } else {
2792 /* Don't load any others if the 0 element isn't there. */
2793 break;
2798 return num_thresholds;
2801 /****************************************************************************
2802 Allocates and loads a new city sprite from the given sprite tags.
2804 tag may be NULL.
2806 See also get_city_sprite, free_city_sprite.
2807 ****************************************************************************/
2808 static struct city_sprite *load_city_sprite(struct tileset *t,
2809 const char *tag)
2811 struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
2812 int style;
2814 /* Store number of styles we have allocated memory for.
2815 * game.control.styles_count might change if client disconnects from
2816 * server and connects new one. */
2817 city_sprite->num_styles = game.control.styles_count;
2818 city_sprite->styles = fc_malloc(city_sprite->num_styles
2819 * sizeof(*city_sprite->styles));
2821 for (style = 0; style < city_sprite->num_styles; style++) {
2822 city_sprite->styles[style].land_num_thresholds =
2823 load_city_thresholds_sprites(t, tag, city_styles[style].graphic,
2824 city_styles[style].graphic_alt,
2825 &city_sprite->styles[style].land_thresholds);
2828 return city_sprite;
2831 /****************************************************************************
2832 Frees a city sprite.
2834 See also get_city_sprite, load_city_sprite.
2835 ****************************************************************************/
2836 static void free_city_sprite(struct city_sprite *city_sprite)
2838 int style;
2840 if (!city_sprite) {
2841 return;
2843 for (style = 0; style < city_sprite->num_styles; style++) {
2844 if (city_sprite->styles[style].land_thresholds) {
2845 free(city_sprite->styles[style].land_thresholds);
2848 free(city_sprite->styles);
2849 free(city_sprite);
2852 /**********************************************************************
2853 Initialize 'sprites' structure based on hardwired tags which
2854 freeciv always requires.
2855 ***********************************************************************/
2856 static void tileset_lookup_sprite_tags(struct tileset *t)
2858 char buffer[512], buffer2[512];
2859 const int W = t->normal_tile_width, H = t->normal_tile_height;
2860 int i, j, f;
2862 fc_assert_ret(t->sprite_hash != NULL);
2864 SET_SPRITE_UNSCALED(treaty_thumb[0], "treaty.disagree_thumb_down");
2865 SET_SPRITE_UNSCALED(treaty_thumb[1], "treaty.agree_thumb_up");
2867 for (j = 0; j < INDICATOR_COUNT; j++) {
2868 const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2870 for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2871 fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
2872 SET_SPRITE_UNSCALED(indicator[j][i], buffer);
2876 SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
2877 SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
2878 SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
2879 if (t->type == TS_ISOMETRIC) {
2880 SET_SPRITE(dither_tile, "t.dither_tile");
2883 if (tileset_is_isometric(tileset)) {
2884 SET_SPRITE_NOTSMOOTH(mask.tile, "mask.tile");
2885 } else {
2886 SET_SPRITE(mask.tile, "mask.tile");
2888 SET_SPRITE(mask.worked_tile, "mask.worked_tile");
2889 SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
2891 SET_SPRITE_UNSCALED(tax_luxury, "s.tax_luxury");
2892 SET_SPRITE_UNSCALED(tax_science, "s.tax_science");
2893 SET_SPRITE_UNSCALED(tax_gold, "s.tax_gold");
2895 tileset_setup_citizen_types(t);
2897 for (i = 0; i < SPACESHIP_COUNT; i++) {
2898 const char *names[SPACESHIP_COUNT]
2899 = {"solar_panels", "life_support", "habitation",
2900 "structural", "fuel", "propulsion", "exhaust"};
2902 fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
2903 SET_SPRITE(spaceship[i], buffer);
2906 for (i = 0; i < CURSOR_LAST; i++) {
2907 for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2908 const char *names[CURSOR_LAST] =
2909 {"goto", "patrol", "paradrop", "nuke", "select",
2910 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2911 struct small_sprite *ss;
2913 fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2914 fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
2915 SET_SPRITE(cursor[i].frame[f], buffer);
2916 if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
2917 t->sprites.cursor[i].hot_x = ss->hot_x;
2918 t->sprites.cursor[i].hot_y = ss->hot_y;
2923 for (i = 0; i < ICON_COUNT; i++) {
2924 const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
2926 fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
2927 SET_SPRITE(icon[i], buffer);
2930 for (i = 0; i < E_COUNT; i++) {
2931 const char *tag = get_event_tag(i);
2933 SET_SPRITE(events[i], tag);
2936 SET_SPRITE(explode.nuke, "explode.nuke");
2938 sprite_vector_init(&t->sprites.explode.unit);
2939 for (i = 0; ; i++) {
2940 struct sprite *sprite;
2942 fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
2943 sprite = load_sprite(t, buffer, TRUE, TRUE);
2944 if (!sprite) {
2945 break;
2947 sprite_vector_append(&t->sprites.explode.unit, sprite);
2950 SET_SPRITE(unit.auto_attack, "unit.auto_attack");
2951 SET_SPRITE(unit.auto_settler, "unit.auto_settler");
2952 SET_SPRITE(unit.auto_explore, "unit.auto_explore");
2953 SET_SPRITE(unit.fortified, "unit.fortified");
2954 SET_SPRITE(unit.fortifying, "unit.fortifying");
2955 SET_SPRITE(unit.go_to, "unit.goto");
2956 SET_SPRITE(unit.irrigate, "unit.irrigate");
2957 SET_SPRITE(unit.plant, "unit.plant");
2958 SET_SPRITE(unit.pillage, "unit.pillage");
2959 SET_SPRITE(unit.sentry, "unit.sentry");
2960 SET_SPRITE(unit.convert, "unit.convert");
2961 SET_SPRITE(unit.stack, "unit.stack");
2962 SET_SPRITE(unit.loaded, "unit.loaded");
2963 SET_SPRITE(unit.transform, "unit.transform");
2964 SET_SPRITE(unit.connect, "unit.connect");
2965 SET_SPRITE(unit.patrol, "unit.patrol");
2966 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
2967 fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
2968 fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
2969 fc_assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
2970 SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
2972 SET_SPRITE(unit.lowfuel, "unit.lowfuel");
2973 SET_SPRITE(unit.tired, "unit.tired");
2975 SET_SPRITE_OPT(unit.action_decision_want, "unit.action_decision_want");
2977 for (i = 0; i < NUM_TILES_HP_BAR; i++) {
2978 fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
2979 SET_SPRITE(unit.hp_bar[i], buffer);
2982 for (i = 0; i < MAX_VET_LEVELS; i++) {
2983 /* Veteran level sprites are optional. For instance "green" units
2984 * usually have no special graphic. */
2985 fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
2986 t->sprites.unit.vet_lev[i] = load_sprite(t, buffer, TRUE, TRUE);
2989 t->sprites.unit.select[0] = NULL;
2990 if (sprite_exists(t, "unit.select0")) {
2991 for (i = 0; i < NUM_TILES_SELECT; i++) {
2992 fc_snprintf(buffer, sizeof(buffer), "unit.select%d", i);
2993 SET_SPRITE(unit.select[i], buffer);
2997 SET_SPRITE(citybar.shields, "citybar.shields");
2998 SET_SPRITE(citybar.food, "citybar.food");
2999 SET_SPRITE(citybar.trade, "citybar.trade");
3000 SET_SPRITE(citybar.occupied, "citybar.occupied");
3001 SET_SPRITE(citybar.background, "citybar.background");
3002 sprite_vector_init(&t->sprites.citybar.occupancy);
3003 for (i = 0; ; i++) {
3004 struct sprite *sprite;
3006 fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
3007 sprite = load_sprite(t, buffer, TRUE, TRUE);
3008 if (!sprite) {
3009 break;
3011 sprite_vector_append(&t->sprites.citybar.occupancy, sprite);
3013 if (t->sprites.citybar.occupancy.size < 2) {
3014 tileset_error(LOG_FATAL, _("Missing necessary citybar.occupancy_N sprites."));
3017 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
3018 SET_EDITOR_SPRITE(erase);
3019 SET_EDITOR_SPRITE(brush);
3020 SET_EDITOR_SPRITE(copy);
3021 SET_EDITOR_SPRITE(paste);
3022 SET_EDITOR_SPRITE(copypaste);
3023 SET_EDITOR_SPRITE(startpos);
3024 SET_EDITOR_SPRITE(terrain);
3025 SET_EDITOR_SPRITE(terrain_resource);
3026 SET_EDITOR_SPRITE(terrain_special);
3027 SET_EDITOR_SPRITE(unit);
3028 SET_EDITOR_SPRITE(city);
3029 SET_EDITOR_SPRITE(vision);
3030 SET_EDITOR_SPRITE(territory);
3031 SET_EDITOR_SPRITE(properties);
3032 SET_EDITOR_SPRITE(road);
3033 SET_EDITOR_SPRITE(military_base);
3034 #undef SET_EDITOR_SPRITE
3036 SET_SPRITE(city.disorder, "city.disorder");
3038 /* Fallbacks for goto path turn numbers:
3039 * path.step_%d, path.exhausted_mp_%d
3040 * --> path.turns_%d
3041 * --> city.size_%d */
3042 #define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name) \
3043 fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
3044 SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer); \
3045 if (t->sprites.path.s[state].turns ## factor_name [i] == NULL) { \
3046 t->sprites.path.s[state].turns ## factor_name [i] = \
3047 t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i]; \
3050 for (i = 0; i < NUM_TILES_DIGITS; i++) {
3051 fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
3052 SET_SPRITE(city.size[i], buffer);
3053 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
3054 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns[i], buffer2, buffer);
3055 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step",,);
3056 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp",,);
3058 fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
3059 SET_SPRITE(city.size_tens[i], buffer);
3060 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
3061 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns_tens[i], buffer2, buffer);
3062 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 0, _tens);
3063 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 0, _tens);
3065 fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
3066 SET_SPRITE_OPT(city.size_hundreds[i], buffer);
3067 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
3068 SET_SPRITE_ALT_OPT(path.s[GTS_MP_LEFT].turns_hundreds[i], buffer2,
3069 buffer);
3070 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 00, _hundreds);
3071 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 00, _hundreds);
3073 fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
3074 SET_SPRITE(city.tile_foodnum[i], buffer);
3075 fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
3076 SET_SPRITE(city.tile_shieldnum[i], buffer);
3077 fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
3078 SET_SPRITE(city.tile_tradenum[i], buffer);
3080 #undef SET_GOTO_TURN_SPRITE
3082 /* Must have at least one upkeep sprite per output type (and unhappy) */
3083 /* The rest are optional; we copy the previous sprite for unspecified ones */
3084 fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
3085 SET_SPRITE(upkeep.unhappy[0], buffer);
3086 for (i = 1; i < MAX_NUM_UPKEEP_SPRITES; i++) {
3087 fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
3088 if (sprite_exists(t, buffer2)) {
3089 SET_SPRITE(upkeep.unhappy[i], buffer2);
3090 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3091 } else {
3092 SET_SPRITE(upkeep.unhappy[i], buffer);
3095 output_type_iterate(o) {
3096 fc_snprintf(buffer, sizeof(buffer),
3097 "upkeep.%s", get_output_identifier(o));
3098 SET_SPRITE_OPT(upkeep.output[o][0], buffer);
3099 for (i = 1; i < MAX_NUM_UPKEEP_SPRITES; i++) {
3100 fc_snprintf(buffer2, sizeof(buffer2),
3101 "upkeep.%s%d", get_output_identifier(o), i+1);
3102 if (sprite_exists(t, buffer2)) {
3103 SET_SPRITE(upkeep.output[o][i], buffer2);
3104 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3105 } else {
3106 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
3107 SET_SPRITE_OPT(upkeep.output[o][i], buffer);
3110 } output_type_iterate_end;
3112 t->max_upkeep_height = calculate_max_upkeep_height(t);
3114 SET_SPRITE(user.attention, "user.attention");
3116 SET_SPRITE_OPT(path.s[GTS_MP_LEFT].specific, "path.normal");
3117 SET_SPRITE_OPT(path.s[GTS_EXHAUSTED_MP].specific, "path.exhausted_mp");
3118 SET_SPRITE_OPT(path.s[GTS_TURN_STEP].specific, "path.step");
3119 SET_SPRITE(path.waypoint, "path.waypoint");
3121 SET_SPRITE_NOTSMOOTH(tx.fog, "tx.fog");
3123 sprite_vector_init(&t->sprites.colors.overlays);
3124 for (i = 0; ; i++) {
3125 struct sprite *sprite;
3127 fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
3128 sprite = load_sprite(t, buffer, TRUE, TRUE);
3129 if (!sprite) {
3130 break;
3132 sprite_vector_append(&t->sprites.colors.overlays, sprite);
3134 if (i == 0) {
3135 tileset_error(LOG_FATAL, _("Missing overlay-color sprite colors.overlay_0."));
3138 /* Chop up and build the overlay graphics. */
3139 sprite_vector_reserve(&t->sprites.city.worked_tile_overlay,
3140 sprite_vector_size(&t->sprites.colors.overlays));
3141 sprite_vector_reserve(&t->sprites.city.unworked_tile_overlay,
3142 sprite_vector_size(&t->sprites.colors.overlays));
3143 for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
3144 struct sprite *color, *color_mask;
3145 struct sprite *worked, *unworked;
3147 color = *sprite_vector_get(&t->sprites.colors.overlays, i);
3148 color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0,
3149 1.0f, FALSE);
3150 worked = crop_sprite(color_mask, 0, 0, W, H,
3151 t->sprites.mask.worked_tile, 0, 0, 1.0f, FALSE);
3152 unworked = crop_sprite(color_mask, 0, 0, W, H,
3153 t->sprites.mask.unworked_tile, 0, 0, 1.0f, FALSE);
3154 free_sprite(color_mask);
3155 t->sprites.city.worked_tile_overlay.p[i] = worked;
3156 t->sprites.city.unworked_tile_overlay.p[i] = unworked;
3161 SET_SPRITE(grid.unavailable, "grid.unavailable");
3162 SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
3164 for (i = 0; i < EDGE_COUNT; i++) {
3165 int be;
3167 if (i == EDGE_UD && t->hex_width == 0) {
3168 continue;
3169 } else if (i == EDGE_LR && t->hex_height == 0) {
3170 continue;
3173 fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
3174 SET_SPRITE(grid.main[i], buffer);
3176 fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
3177 SET_SPRITE(grid.city[i], buffer);
3179 fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
3180 SET_SPRITE(grid.worked[i], buffer);
3182 fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
3183 SET_SPRITE(grid.selected[i], buffer);
3185 fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
3186 SET_SPRITE(grid.coastline[i], buffer);
3188 for (be = 0; be < 2; be++) {
3189 fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
3190 edge_name[i][be]);
3191 SET_SPRITE(grid.borders[i][be], buffer);
3196 switch (t->darkness_style) {
3197 case DARKNESS_NONE:
3198 /* Nothing. */
3199 break;
3200 case DARKNESS_ISORECT:
3202 /* Isometric: take a single tx.darkness tile and split it into 4. */
3203 struct sprite *darkness = load_sprite(t, "tx.darkness", TRUE, FALSE);
3204 const int ntw = t->normal_tile_width, nth = t->normal_tile_height;
3205 int offsets[4][2] = {{ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
3207 if (!darkness) {
3208 tileset_error(LOG_FATAL, _("Sprite tx.darkness missing."));
3210 for (i = 0; i < 4; i++) {
3211 t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
3212 offsets[i][1], ntw / 2,
3213 nth / 2, NULL, 0, 0, 1.0f,
3214 FALSE);
3217 break;
3218 case DARKNESS_CARD_SINGLE:
3219 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3220 enum direction8 dir = t->cardinal_tileset_dirs[i];
3222 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3223 dir_get_tileset_name(dir));
3224 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3226 break;
3227 case DARKNESS_CARD_FULL:
3228 for (i = 1; i < t->num_index_cardinal; i++) {
3229 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3230 cardinal_index_str(t, i));
3231 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3233 break;
3234 case DARKNESS_CORNER:
3235 t->sprites.tx.fullfog = fc_realloc(t->sprites.tx.fullfog,
3236 81 * sizeof(*t->sprites.tx.fullfog));
3237 for (i = 0; i < 81; i++) {
3238 /* Unknown, fog, known. */
3239 char ids[] = {'u', 'f', 'k'};
3240 char buf[512] = "t.fog";
3241 int values[4], vi, k = i;
3243 for (vi = 0; vi < 4; vi++) {
3244 values[vi] = k % 3;
3245 k /= 3;
3247 cat_snprintf(buf, sizeof(buf), "_%c", ids[values[vi]]);
3249 fc_assert(k == 0);
3251 t->sprites.tx.fullfog[i] = load_sprite(t, buf, TRUE, FALSE);
3253 break;
3256 /* no other place to initialize these variables */
3257 sprite_vector_init(&t->sprites.nation_flag);
3258 sprite_vector_init(&t->sprites.nation_shield);
3261 /**************************************************************************
3262 Load sprites of one river type.
3263 **************************************************************************/
3264 static bool load_river_sprites(struct tileset *t,
3265 struct river_sprites *store, const char *tag_pfx)
3267 int i;
3268 char buffer[512];
3270 for (i = 0; i < t->num_index_cardinal; i++) {
3271 fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
3272 tag_pfx, cardinal_index_str(t, i));
3273 store->spec[i] = load_sprite(t, buffer, TRUE, TRUE);
3274 if (store->spec[i] == NULL) {
3275 return FALSE;
3279 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3280 fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%s",
3281 tag_pfx, dir_get_tileset_name(t->cardinal_tileset_dirs[i]));
3282 store->outlet[i] = load_sprite(t, buffer, TRUE, TRUE);
3283 if (store->outlet[i] == NULL) {
3284 if (t->cardinal_tileset_dirs[i] == DIR8_NORTHWEST
3285 || t->cardinal_tileset_dirs[i] == DIR8_NORTHEAST
3286 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHEAST
3287 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHWEST) {
3288 log_debug("Missing \"%s\", support for this is deprecated.", buffer);
3289 } else {
3290 return FALSE;
3295 return TRUE;
3298 /**************************************************************************
3299 Frees any internal buffers which are created by load_sprite. Should
3300 be called after the last (for a given period of time) load_sprite
3301 call. This saves a fair amount of memory, but it will take extra time
3302 the next time we start loading sprites again.
3303 **************************************************************************/
3304 void finish_loading_sprites(struct tileset *t)
3306 specfile_list_iterate(t->specfiles, sf) {
3307 if (sf->big_sprite) {
3308 free_sprite(sf->big_sprite);
3309 sf->big_sprite = NULL;
3311 } specfile_list_iterate_end;
3314 /**********************************************************************
3315 Load the tiles; requires tilespec_read_toplevel() called previously.
3316 Leads to tile_sprites being allocated and filled with pointers
3317 to sprites. Also sets up and populates sprite_hash, and calls func
3318 to initialize 'sprites' structure.
3319 ***********************************************************************/
3320 void tileset_load_tiles(struct tileset *t)
3322 tileset_lookup_sprite_tags(t);
3323 finish_loading_sprites(t);
3326 /**********************************************************************
3327 Lookup sprite to match tag, or else to match alt if don't find,
3328 or else return NULL, and emit log message.
3329 ***********************************************************************/
3330 struct sprite *tiles_lookup_sprite_tag_alt(struct tileset *t,
3331 enum log_level level,
3332 const char *tag, const char *alt,
3333 const char *what,
3334 const char *name,
3335 bool scale)
3337 struct sprite *sp;
3339 /* (should get sprite_hash before connection) */
3340 fc_assert_ret_val_msg(NULL != t->sprite_hash, NULL,
3341 "attempt to lookup for %s \"%s\" before "
3342 "sprite_hash setup", what, name);
3344 sp = load_sprite(t, tag, scale, TRUE);
3345 if (sp) return sp;
3347 sp = load_sprite(t, alt, scale, TRUE);
3348 if (sp) {
3349 log_verbose("Using alternate graphic \"%s\" "
3350 "(instead of \"%s\") for %s \"%s\".",
3351 alt, tag, what, name);
3352 return sp;
3355 tileset_error(level, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3356 tag, alt, what, name);
3358 return NULL;
3361 /**********************************************************************
3362 Helper function to load sprite for one unit orientation.
3363 Returns FALSE if a needed sprite was not found.
3364 ***********************************************************************/
3365 static bool tileset_setup_unit_direction(struct tileset *t,
3366 int uidx,
3367 const char *base_str,
3368 enum direction8 dir,
3369 bool has_icon)
3371 char buf[2048];
3372 enum direction8 loaddir = dir;
3375 * There may be more orientations available in this tileset than are
3376 * needed, if an oriented unit set has been re-used between tilesets.
3378 * Don't bother loading unused ones, unless they might be used by
3379 * unit_default_orientation (logic here mirrors get_unittype_sprite()).
3381 if (!(dir == t->unit_default_orientation && !has_icon)
3382 && !is_valid_tileset_dir(t, dir)) {
3383 /* Instead we copy a nearby valid dir's sprite, so we're not caught
3384 * out in case this tileset is used with an incompatible topology,
3385 * although it'll be ugly. */
3386 do {
3387 loaddir = dir_cw(loaddir);
3388 /* This loop _should_ terminate... */
3389 fc_assert_ret_val(loaddir != dir, FALSE);
3390 } while (!is_valid_tileset_dir(t, loaddir));
3393 fc_snprintf(buf, sizeof(buf), "%s_%s", base_str,
3394 dir_get_tileset_name(loaddir));
3396 /* We don't use _alt graphics here, as that could lead to loading
3397 * real icon gfx, but alternative orientation gfx. Tileset author
3398 * probably meant icon gfx to be used as fallback for all orientations */
3399 t->sprites.units.facing[uidx][dir] = load_sprite(t, buf, TRUE, TRUE);
3401 if (t->sprites.units.facing[uidx][dir] != NULL) {
3402 return TRUE;
3405 return FALSE;
3408 /**********************************************************************
3409 Try to setup all unit type sprites from single tag
3410 ***********************************************************************/
3411 bool static tileset_setup_unit_type_from_tag(struct tileset *t,
3412 int uidx, const char *tag)
3414 bool has_icon, facing_sprites = TRUE;
3416 t->sprites.units.icon[uidx] = load_sprite(t, tag, TRUE, TRUE);
3417 has_icon = t->sprites.units.icon[uidx] != NULL;
3419 #define LOAD_FACING_SPRITE(dir) \
3420 if (!tileset_setup_unit_direction(t, uidx, tag, dir, has_icon)) { \
3421 facing_sprites = FALSE; \
3424 LOAD_FACING_SPRITE(DIR8_NORTHWEST);
3425 LOAD_FACING_SPRITE(DIR8_NORTH);
3426 LOAD_FACING_SPRITE(DIR8_NORTHEAST);
3427 LOAD_FACING_SPRITE(DIR8_WEST);
3428 LOAD_FACING_SPRITE(DIR8_EAST);
3429 LOAD_FACING_SPRITE(DIR8_SOUTHWEST);
3430 LOAD_FACING_SPRITE(DIR8_SOUTH);
3431 LOAD_FACING_SPRITE(DIR8_SOUTHEAST);
3433 if (!has_icon && !facing_sprites) {
3434 /* Neither icon gfx or orientation sprites */
3435 return FALSE;
3438 return TRUE;
3440 #undef LOAD_FACING_SPRITE
3443 /**********************************************************************
3444 Set unit_type sprite value; should only happen after
3445 tilespec_load_tiles().
3446 ***********************************************************************/
3447 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
3449 int uidx = utype_index(ut);
3451 if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
3452 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
3453 tileset_error(LOG_FATAL, _("Missing %s unit sprite for tags \"%s\" and alternative \"%s\"."),
3454 utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
3457 if (!t->sprites.units.icon[uidx]) {
3458 if (!direction8_is_valid(t->unit_default_orientation)) {
3459 tileset_error(LOG_FATAL, "Unit type %s has no unoriented sprite and "
3460 "tileset has no unit_default_orientation.",
3461 utype_rule_name(ut));
3462 } else {
3463 /* We're guaranteed to have an oriented sprite corresponding to
3464 * unit_default_orientation, because tileset_setup_unit_type_from_tag()
3465 * checked for this. */
3466 fc_assert(t->sprites.units.facing[uidx][t->unit_default_orientation]
3467 != NULL);
3472 /**********************************************************************
3473 Set improvement_type sprite value; should only happen after
3474 tilespec_load_tiles().
3475 ***********************************************************************/
3476 void tileset_setup_impr_type(struct tileset *t,
3477 struct impr_type *pimprove)
3479 t->sprites.building[improvement_index(pimprove)] =
3480 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, pimprove->graphic_str,
3481 pimprove->graphic_alt, "improvement",
3482 improvement_rule_name(pimprove), FALSE);
3484 /* should maybe do something if NULL, eg generic default? */
3487 /**********************************************************************
3488 Set tech_type sprite value; should only happen after
3489 tilespec_load_tiles().
3490 ***********************************************************************/
3491 void tileset_setup_tech_type(struct tileset *t,
3492 struct advance *padvance)
3494 if (valid_advance(padvance)) {
3495 t->sprites.tech[advance_index(padvance)] =
3496 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, padvance->graphic_str,
3497 padvance->graphic_alt, "technology",
3498 advance_rule_name(padvance), FALSE);
3500 /* should maybe do something if NULL, eg generic default? */
3501 } else {
3502 t->sprites.tech[advance_index(padvance)] = NULL;
3506 /****************************************************************************
3507 Set extra sprite values; should only happen after
3508 tilespec_load_tiles().
3509 ****************************************************************************/
3510 void tileset_setup_extra(struct tileset *t,
3511 struct extra_type *pextra)
3513 const int id = extra_index(pextra);
3514 enum extrastyle_id extrastyle;
3516 if (!fc_strcasecmp(pextra->graphic_str, "none")) {
3517 /* Extra without graphics */
3518 t->sprites.extras[id].extrastyle = extrastyle_id_invalid();
3519 } else {
3521 if (!estyle_hash_lookup(t->estyle_hash, pextra->graphic_str,
3522 &extrastyle)
3523 && !estyle_hash_lookup(t->estyle_hash, pextra->graphic_alt,
3524 &extrastyle)) {
3525 tileset_error(LOG_FATAL, _("No extrastyle for \"%s\" or \"%s\"."),
3526 pextra->graphic_str,
3527 pextra->graphic_alt);
3530 if (is_extra_caused_by(pextra, EC_RESOURCE) && extrastyle != ESTYLE_SINGLE1) {
3531 tileset_error(LOG_FATAL,
3532 /* Not translated as this should go away before next release. */
3533 "Extrastyle \"%s\" given for resource \"%s\", only \"Single1\" supported.",
3534 extrastyle_id_name(extrastyle));
3537 t->sprites.extras[id].extrastyle = extrastyle;
3539 extra_type_list_append(t->style_lists[extrastyle], pextra);
3541 if (extra_has_flag(pextra, EF_SHOW_FLAG)) {
3542 extra_type_list_append(t->flagged_bases_list, pextra);
3545 switch (extrastyle) {
3546 case ESTYLE_3LAYER:
3547 tileset_setup_base(t, pextra);
3548 break;
3550 case ESTYLE_ROAD_ALL_SEPARATE:
3551 case ESTYLE_ROAD_PARITY_COMBINED:
3552 case ESTYLE_ROAD_ALL_COMBINED:
3553 case ESTYLE_RIVER:
3554 tileset_setup_road(t, pextra);
3555 break;
3557 case ESTYLE_SINGLE1:
3558 case ESTYLE_SINGLE2:
3559 SET_SPRITE_ALT(extras[id].u.single, pextra->graphic_str, pextra->graphic_alt);
3560 break;
3562 case ESTYLE_CARDINALS:
3564 int i;
3565 char buffer[512];
3567 /* We use direction-specific irrigation and farmland graphics, if they
3568 * are available. If not, we just fall back to the basic irrigation
3569 * graphics. */
3570 for (i = 0; i < t->num_index_cardinal; i++) {
3571 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3572 pextra->graphic_str, cardinal_index_str(t, i));
3573 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3574 TRUE, TRUE);
3575 if (!t->sprites.extras[id].u.cardinals[i]) {
3576 t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3577 pextra->graphic_str, TRUE,
3578 TRUE);
3580 if (!t->sprites.extras[id].u.cardinals[i]) {
3581 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3582 pextra->graphic_alt, cardinal_index_str(t, i));
3583 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3584 TRUE, TRUE);
3586 if (!t->sprites.extras[id].u.cardinals[i]) {
3587 t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3588 pextra->graphic_alt, TRUE,
3589 TRUE);
3591 if (!t->sprites.extras[id].u.cardinals[i]) {
3592 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are "
3593 "both missing."),
3594 pextra->graphic_str, pextra->graphic_alt);
3598 break;
3599 case ESTYLE_COUNT:
3600 break;
3604 if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
3605 t->sprites.extras[id].activity = NULL;
3606 } else {
3607 t->sprites.extras[id].activity = load_sprite(t, pextra->activity_gfx,
3608 TRUE, TRUE);
3609 if (t->sprites.extras[id].activity == NULL) {
3610 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt,
3611 TRUE, TRUE);
3613 if (t->sprites.extras[id].activity == NULL) {
3614 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt2,
3615 TRUE, TRUE);
3617 if (t->sprites.extras[id].activity == NULL) {
3618 tileset_error(LOG_FATAL, _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
3619 extra_rule_name(pextra), pextra->activity_gfx,
3620 pextra->act_gfx_alt, pextra->act_gfx_alt2);
3624 if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
3625 t->sprites.extras[id].rmact = NULL;
3626 } else {
3627 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx, TRUE,
3628 TRUE);
3629 if (t->sprites.extras[id].rmact == NULL) {
3630 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx_alt,
3631 TRUE, TRUE);
3632 if (t->sprites.extras[id].rmact == NULL) {
3633 tileset_error(LOG_FATAL, _("Missing %s removal activity sprite for tags \"%s\" and alternative \"%s\"."),
3634 extra_rule_name(pextra), pextra->rmact_gfx, pextra->rmact_gfx_alt);
3640 /****************************************************************************
3641 Set road sprite values; should only happen after
3642 tilespec_load_tiles().
3643 ****************************************************************************/
3644 static void tileset_setup_road(struct tileset *t,
3645 struct extra_type *pextra)
3647 char full_tag_name[MAX_LEN_NAME + strlen("_isolated")];
3648 char full_alt_name[MAX_LEN_NAME + strlen("_isolated")];
3649 const int id = extra_index(pextra);
3650 int i;
3651 enum extrastyle_id extrastyle = t->sprites.extras[id].extrastyle;
3653 /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3654 ESTYLE_ROAD_PARITY_COMBINED. */
3655 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3656 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3657 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3658 "%s_isolated", pextra->graphic_str);
3659 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3660 "%s_isolated", pextra->graphic_alt);
3662 SET_SPRITE_ALT(extras[id].u.road.isolated, full_tag_name, full_alt_name);
3665 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
3666 /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each road type:
3667 * one going off in each direction. */
3668 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3669 enum direction8 dir = t->valid_tileset_dirs[i];
3670 const char *dir_name = dir_get_tileset_name(dir);
3672 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3673 "%s_%s", pextra->graphic_str, dir_name);
3674 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3675 "%s_%s", pextra->graphic_alt, dir_name);
3677 SET_SPRITE_ALT(extras[id].u.road.ru.dir[i], full_tag_name, full_alt_name);
3679 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3680 int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
3682 /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road type:
3683 * 16 each for cardinal and diagonal directions. Each set
3684 * of 16 provides a NSEW-indexed sprite to provide connectors for
3685 * all rails in the cardinal/diagonal directions. The 0 entry is
3686 * unused (the "isolated" sprite is used instead). */
3688 for (i = 1; i < num_index; i++) {
3689 char c[64] = "", d[64] = "";
3691 for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
3692 int value = (i >> j) & 1;
3694 cat_snprintf(c, sizeof(c), "%s%d",
3695 dir_get_tileset_name(t->valid_tileset_dirs[2 * j]),
3696 value);
3697 cat_snprintf(d, sizeof(d), "%s%d",
3698 dir_get_tileset_name(t->valid_tileset_dirs[2 * j + 1]),
3699 value);
3702 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3703 "%s_c_%s", pextra->graphic_str, c);
3704 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3705 "%s_c_%s", pextra->graphic_alt, c);
3707 SET_SPRITE_ALT(extras[id].u.road.ru.combo.even[i], full_tag_name, full_alt_name);
3709 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3710 "%s_d_%s", pextra->graphic_str, d);
3711 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3712 "%s_d_%s", pextra->graphic_alt, d);
3714 SET_SPRITE_ALT(extras[id].u.road.ru.combo.odd[i], full_tag_name, full_alt_name);
3716 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
3717 /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
3718 * Just go around clockwise, with all combinations. */
3719 for (i = 0; i < t->num_index_valid; i++) {
3720 char *idx_str = valid_index_str(t, i);
3722 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3723 "%s_%s", pextra->graphic_str, idx_str);
3724 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3725 "%s_%s", pextra->graphic_alt, idx_str);
3727 SET_SPRITE_ALT(extras[id].u.road.ru.total[i], full_tag_name, full_alt_name);
3729 } else if (extrastyle == ESTYLE_RIVER) {
3730 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3731 pextra->graphic_str)) {
3732 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3733 pextra->graphic_alt)) {
3734 tileset_error(LOG_FATAL, _("Cannot load river \"%s\" or \"%s\""),
3735 pextra->graphic_str, pextra->graphic_alt);
3738 } else {
3739 fc_assert(FALSE);
3742 /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3743 * ESTYLE_ROAD_PARITY_COMBINED. */
3744 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3745 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3746 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3747 enum direction8 dir = t->valid_tileset_dirs[i];
3749 if (!is_cardinal_tileset_dir(t, dir)) {
3750 const char *dtn = dir_get_tileset_name(dir);
3752 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3753 "%s_c_%s", pextra->graphic_str, dtn);
3754 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3755 "%s_c_%s", pextra->graphic_alt, dtn);
3757 SET_SPRITE_ALT_OPT(extras[id].u.road.corner[dir], full_tag_name, full_alt_name);
3763 /****************************************************************************
3764 Set base sprite values; should only happen after
3765 tilespec_load_tiles().
3766 ****************************************************************************/
3767 static void tileset_setup_base(struct tileset *t,
3768 const struct extra_type *pextra)
3770 char full_tag_name[MAX_LEN_NAME + strlen("_fg")];
3771 const int id = extra_index(pextra);
3773 fc_assert_ret(id >= 0 && id < extra_count());
3775 sz_strlcpy(full_tag_name, pextra->graphic_str);
3776 strcat(full_tag_name, "_bg");
3777 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3778 TRUE, TRUE);
3780 sz_strlcpy(full_tag_name, pextra->graphic_str);
3781 strcat(full_tag_name, "_mg");
3782 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3783 TRUE, TRUE);
3785 sz_strlcpy(full_tag_name, pextra->graphic_str);
3786 strcat(full_tag_name, "_fg");
3787 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3788 TRUE, TRUE);
3790 if (t->sprites.extras[id].u.bmf.background == NULL
3791 && t->sprites.extras[id].u.bmf.middleground == NULL
3792 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3793 /* No primary graphics at all. Try alternative */
3794 log_verbose("Using alternate graphic \"%s\" "
3795 "(instead of \"%s\") for extra \"%s\".",
3796 pextra->graphic_alt, pextra->graphic_str,
3797 extra_rule_name(pextra));
3799 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3800 strcat(full_tag_name, "_bg");
3801 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3802 TRUE, TRUE);
3804 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3805 strcat(full_tag_name, "_mg");
3806 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3807 TRUE, TRUE);
3809 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3810 strcat(full_tag_name, "_fg");
3811 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3812 TRUE, TRUE);
3814 if (t->sprites.extras[id].u.bmf.background == NULL
3815 && t->sprites.extras[id].u.bmf.middleground == NULL
3816 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3817 /* Cannot find alternative graphics either */
3818 tileset_error(LOG_FATAL, _("No graphics for extra \"%s\" at all!"),
3819 extra_rule_name(pextra));
3824 /**********************************************************************
3825 Set tile_type sprite values; should only happen after
3826 tilespec_load_tiles().
3827 ***********************************************************************/
3828 void tileset_setup_tile_type(struct tileset *t,
3829 const struct terrain *pterrain)
3831 struct drawing_data *draw;
3832 struct sprite *sprite;
3833 char buffer[MAX_LEN_NAME + 20];
3834 int i, l;
3836 if (0 == strlen(terrain_rule_name(pterrain))) {
3837 return;
3840 if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
3841 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
3842 tileset_error(LOG_FATAL, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3843 terrain_rule_name(pterrain), pterrain->graphic_str,
3844 pterrain->graphic_alt);
3847 if (draw->init) {
3848 t->sprites.drawing[terrain_index(pterrain)] = draw;
3849 return;
3852 /* Set up each layer of the drawing. */
3853 for (l = 0; l < draw->num_layers; l++) {
3854 struct drawing_layer *dlp = &draw->layer[l];
3855 struct tileset_layer *tslp = &t->layers[l];
3856 sprite_vector_init(&dlp->base);
3857 sprite_vector_init(&dlp->allocated);
3859 switch (dlp->sprite_type) {
3860 case CELL_WHOLE:
3861 switch (dlp->match_style) {
3862 case MATCH_NONE:
3863 /* Load whole sprites for this tile. */
3864 for (i = 0; ; i++) {
3865 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
3866 l, draw->name, i + 1);
3867 sprite = load_sprite(t, buffer, TRUE, FALSE);
3868 if (!sprite) {
3869 break;
3871 sprite_vector_reserve(&dlp->base, i + 1);
3872 dlp->base.p[i] = sprite;
3874 /* check for base sprite, allowing missing sprites above base */
3875 if (0 == i && 0 == l) {
3876 /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
3877 tileset_error(LOG_FATAL, _("Missing base sprite for tag \"%s\"."), buffer);
3879 break;
3880 case MATCH_SAME:
3881 /* Load 16 cardinally-matched sprites. */
3882 for (i = 0; i < t->num_index_cardinal; i++) {
3883 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
3884 l, draw->name, cardinal_index_str(t, i));
3885 dlp->match[i] =
3886 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3887 "matched terrain",
3888 terrain_rule_name(pterrain), TRUE);
3890 break;
3891 case MATCH_PAIR:
3892 case MATCH_FULL:
3893 fc_assert(FALSE); /* not yet defined */
3894 break;
3896 break;
3897 case CELL_CORNER:
3899 const int count = dlp->match_indices;
3900 int number = NUM_CORNER_DIRS;
3902 switch (dlp->match_style) {
3903 case MATCH_NONE:
3904 /* do nothing */
3905 break;
3906 case MATCH_PAIR:
3907 case MATCH_SAME:
3908 /* N directions (NSEW) * 3 dimensions of matching */
3909 fc_assert(count == 2);
3910 number = NUM_CORNER_DIRS * 2 * 2 * 2;
3911 break;
3912 case MATCH_FULL:
3913 default:
3914 /* N directions (NSEW) * 3 dimensions of matching */
3915 /* could use exp() or expi() here? */
3916 number = NUM_CORNER_DIRS * count * count * count;
3917 break;
3920 dlp->cells
3921 = fc_calloc(number, sizeof(*dlp->cells));
3923 for (i = 0; i < number; i++) {
3924 enum direction4 dir = i % NUM_CORNER_DIRS;
3925 int value = i / NUM_CORNER_DIRS;
3927 switch (dlp->match_style) {
3928 case MATCH_NONE:
3929 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
3930 l, draw->name, direction4letters[dir]);
3931 dlp->cells[i] =
3932 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3933 "cell terrain",
3934 terrain_rule_name(pterrain), TRUE);
3935 break;
3936 case MATCH_SAME:
3937 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
3938 l, draw->name, direction4letters[dir],
3939 (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
3940 dlp->cells[i] =
3941 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3942 "same cell terrain",
3943 terrain_rule_name(pterrain), TRUE);
3944 break;
3945 case MATCH_PAIR:
3946 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
3947 l, draw->name, direction4letters[dir],
3948 tslp->match_types[dlp->match_index[(value) & 1]][0],
3949 tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
3950 tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
3951 dlp->cells[i] =
3952 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3953 "cell pair terrain",
3954 terrain_rule_name(pterrain), TRUE);
3955 break;
3956 case MATCH_FULL:
3958 int this = dlp->match_index[0];
3959 int n, s, e, w;
3960 int v1, v2, v3;
3962 v1 = dlp->match_index[value % count];
3963 value /= count;
3964 v2 = dlp->match_index[value % count];
3965 value /= count;
3966 v3 = dlp->match_index[value % count];
3968 fc_assert(v1 < count && v2 < count && v3 < count);
3970 /* Assume merged cells. This should be a separate option. */
3971 switch (dir) {
3972 case DIR4_NORTH:
3973 s = this;
3974 w = v1;
3975 n = v2;
3976 e = v3;
3977 break;
3978 case DIR4_EAST:
3979 w = this;
3980 n = v1;
3981 e = v2;
3982 s = v3;
3983 break;
3984 case DIR4_SOUTH:
3985 n = this;
3986 e = v1;
3987 s = v2;
3988 w = v3;
3989 break;
3990 case DIR4_WEST:
3991 default: /* avoid warnings */
3992 e = this;
3993 s = v1;
3994 w = v2;
3995 n = v3;
3996 break;
3999 /* Use first character of match_types,
4000 * already checked for uniqueness. */
4001 fc_snprintf(buffer, sizeof(buffer),
4002 "t.l%d.cellgroup_%c_%c_%c_%c", l,
4003 tslp->match_types[n][0], tslp->match_types[e][0],
4004 tslp->match_types[s][0], tslp->match_types[w][0]);
4005 sprite = load_sprite(t, buffer, TRUE, FALSE);
4007 if (sprite) {
4008 /* Crop the sprite to separate this cell. */
4009 int vec_size = sprite_vector_size(&dlp->allocated);
4011 const int W = t->normal_tile_width;
4012 const int H = t->normal_tile_height;
4013 int x[4] = {W / 4, W / 4, 0, W / 2};
4014 int y[4] = {H / 2, 0, H / 4, H / 4};
4015 int xo[4] = {0, 0, -W / 2, W / 2};
4016 int yo[4] = {H / 2, -H / 2, 0, 0};
4018 sprite = crop_sprite(sprite, x[dir], y[dir], W / 2, H / 2,
4019 t->sprites.mask.tile, xo[dir], yo[dir], 1.0f,
4020 FALSE);
4021 /* We allocated new sprite with crop_sprite. Store its
4022 * address so we can free it. */
4023 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
4024 dlp->allocated.p[vec_size] = sprite;
4025 } else {
4026 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer);
4029 dlp->cells[i] = sprite;
4031 break;
4035 break;
4039 /* try an optional special name */
4040 fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
4041 draw->blender =
4042 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, buffer, "",
4043 "blend terrain",
4044 terrain_rule_name(pterrain), TRUE);
4046 if (draw->blending > 0) {
4047 const int bl = draw->blending - 1;
4049 if (NULL == draw->blender) {
4050 int li = 0;
4052 /* try an already loaded base */
4053 while (NULL == draw->blender
4054 && li < draw->blending
4055 && 0 < draw->layer[li].base.size) {
4056 draw->blender = draw->layer[li++].base.p[0];
4060 if (NULL == draw->blender) {
4061 /* try an unloaded base name */
4062 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", bl, draw->name);
4063 draw->blender =
4064 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4065 "base (blend) terrain",
4066 terrain_rule_name(pterrain), TRUE);
4070 if (NULL != draw->blender) {
4071 /* Set up blending sprites. This only works in iso-view! */
4072 const int W = t->normal_tile_width;
4073 const int H = t->normal_tile_height;
4074 const int offsets[4][2] = {
4075 {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4077 enum direction4 dir = 0;
4079 for (; dir < 4; dir++) {
4080 draw->blend[dir] = crop_sprite(draw->blender, offsets[dir][0],
4081 offsets[dir][1], W / 2, H / 2,
4082 t->sprites.dither_tile, 0, 0, 1.0f,
4083 FALSE);
4087 draw->init = TRUE;
4088 t->sprites.drawing[terrain_index(pterrain)] = draw;
4091 /**********************************************************************
4092 Set government sprite value; should only happen after
4093 tilespec_load_tiles().
4094 ***********************************************************************/
4095 void tileset_setup_government(struct tileset *t,
4096 struct government *gov)
4098 t->sprites.government[government_index(gov)] =
4099 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, gov->graphic_str,
4100 gov->graphic_alt, "government",
4101 government_rule_name(gov), FALSE);
4103 /* should probably do something if NULL, eg generic default? */
4106 /**********************************************************************
4107 Set nation flag sprite value; should only happen after
4108 tilespec_load_tiles().
4109 ***********************************************************************/
4110 void tileset_setup_nation_flag(struct tileset *t,
4111 struct nation_type *nation)
4113 char *tags[] = {nation->flag_graphic_str,
4114 nation->flag_graphic_alt,
4115 "unknown", NULL};
4116 int i;
4117 struct sprite *flag = NULL, *shield = NULL;
4118 char buf[1024];
4120 for (i = 0; tags[i] && !flag; i++) {
4121 fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
4122 flag = load_sprite(t, buf, TRUE, TRUE);
4124 for (i = 0; tags[i] && !shield; i++) {
4125 fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
4126 shield = load_sprite(t, buf, TRUE, TRUE);
4128 if (!flag || !shield) {
4129 /* Should never get here because of the f.unknown fallback. */
4130 tileset_error(LOG_FATAL, _("Nation %s: no national flag."), nation_rule_name(nation));
4133 sprite_vector_reserve(&t->sprites.nation_flag, nation_count());
4134 t->sprites.nation_flag.p[nation_index(nation)] = flag;
4136 sprite_vector_reserve(&t->sprites.nation_shield, nation_count());
4137 t->sprites.nation_shield.p[nation_index(nation)] = shield;
4140 /**********************************************************************
4141 Return the flag graphic to be used by the city.
4142 ***********************************************************************/
4143 struct sprite *get_city_flag_sprite(const struct tileset *t,
4144 const struct city *pcity)
4146 return get_nation_flag_sprite(t, nation_of_city(pcity));
4149 /**********************************************************************
4150 Return a sprite for the national flag for this unit.
4151 ***********************************************************************/
4152 static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
4153 const struct unit *punit)
4155 struct nation_type *pnation = nation_of_unit(punit);
4157 if (gui_options.draw_unit_shields) {
4158 return t->sprites.nation_shield.p[nation_index(pnation)];
4159 } else {
4160 return t->sprites.nation_flag.p[nation_index(pnation)];
4164 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
4165 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
4167 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
4168 (fc_assert(s != NULL), \
4169 sprs->sprite = s, \
4170 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
4171 sprs->offset_x = x_offset, \
4172 sprs->offset_y = y_offset, \
4173 sprs++)
4174 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
4175 #define ADD_SPRITE_FULL(s) \
4176 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4178 /**************************************************************************
4179 Assemble some data that is used in building the tile sprite arrays.
4180 (map_x, map_y) : the (normalized) map position
4181 The values we fill in:
4182 tterrain_near : terrain types of all adjacent terrain
4183 tspecial_near : specials of all adjacent terrain
4184 **************************************************************************/
4185 static void build_tile_data(const struct tile *ptile,
4186 struct terrain *pterrain,
4187 struct terrain **tterrain_near,
4188 bv_extras *textras_near)
4190 enum direction8 dir;
4192 /* Loop over all adjacent tiles. We should have an iterator for this. */
4193 for (dir = 0; dir < 8; dir++) {
4194 struct tile *tile1 = mapstep(ptile, dir);
4196 if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
4197 struct terrain *terrain1 = tile_terrain(tile1);
4199 if (NULL != terrain1) {
4200 tterrain_near[dir] = terrain1;
4201 textras_near[dir] = *tile_extras(tile1);
4202 continue;
4204 log_error("build_tile_data() tile (%d,%d) has no terrain!",
4205 TILE_XY(tile1));
4207 /* At the edges of the (known) map, pretend the same terrain continued
4208 * past the edge of the map. */
4209 tterrain_near[dir] = pterrain;
4210 BV_CLR_ALL(textras_near[dir]);
4214 /**********************************************************************
4215 Fill in the sprite array for the unit type.
4216 ***********************************************************************/
4217 static int fill_unit_type_sprite_array(const struct tileset *t,
4218 struct drawn_sprite *sprs,
4219 const struct unit_type *putype,
4220 enum direction8 facing)
4222 struct drawn_sprite *save_sprs = sprs;
4223 struct sprite *uspr = get_unittype_sprite(t, putype, facing);
4225 ADD_SPRITE(uspr, TRUE,
4226 FULL_TILE_X_OFFSET + t->unit_offset_x,
4227 FULL_TILE_Y_OFFSET + t->unit_offset_y);
4229 return sprs - save_sprs;
4232 /**********************************************************************
4233 Fill in the sprite array for the unit.
4234 ***********************************************************************/
4235 static int fill_unit_sprite_array(const struct tileset *t,
4236 struct drawn_sprite *sprs,
4237 const struct unit *punit,
4238 bool stack, bool backdrop)
4240 struct drawn_sprite *save_sprs = sprs;
4241 int ihp;
4242 struct unit_type *ptype = unit_type_get(punit);
4244 if (backdrop) {
4245 if (!gui_options.solid_color_behind_units) {
4246 ADD_SPRITE(get_unit_nation_flag_sprite(t, punit), TRUE,
4247 FULL_TILE_X_OFFSET + t->unit_flag_offset_x,
4248 FULL_TILE_Y_OFFSET + t->unit_flag_offset_y);
4249 } else {
4250 /* Taken care of in the LAYER_BACKGROUND. */
4254 /* Add the sprite for the unit type. */
4255 sprs += fill_unit_type_sprite_array(t, sprs, ptype,
4256 punit->facing);
4258 if (t->sprites.unit.loaded && unit_transported(punit)) {
4259 ADD_SPRITE_FULL(t->sprites.unit.loaded);
4262 if (punit->activity != ACTIVITY_IDLE) {
4263 struct sprite *s = NULL;
4265 switch (punit->activity) {
4266 case ACTIVITY_MINE:
4267 if (punit->activity_target == NULL) {
4268 s = t->sprites.unit.plant;
4269 } else {
4270 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4272 break;
4273 case ACTIVITY_IRRIGATE:
4274 if (punit->activity_target == NULL) {
4275 s = t->sprites.unit.irrigate;
4276 } else {
4277 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4279 break;
4280 case ACTIVITY_POLLUTION:
4281 case ACTIVITY_FALLOUT:
4282 s = t->sprites.extras[extra_index(punit->activity_target)].rmact;
4283 break;
4284 case ACTIVITY_PILLAGE:
4285 s = t->sprites.unit.pillage;
4286 break;
4287 case ACTIVITY_EXPLORE:
4288 s = t->sprites.unit.auto_explore;
4289 break;
4290 case ACTIVITY_FORTIFIED:
4291 s = t->sprites.unit.fortified;
4292 break;
4293 case ACTIVITY_FORTIFYING:
4294 s = t->sprites.unit.fortifying;
4295 break;
4296 case ACTIVITY_SENTRY:
4297 s = t->sprites.unit.sentry;
4298 break;
4299 case ACTIVITY_GOTO:
4300 s = t->sprites.unit.go_to;
4301 break;
4302 case ACTIVITY_TRANSFORM:
4303 s = t->sprites.unit.transform;
4304 break;
4305 case ACTIVITY_BASE:
4306 case ACTIVITY_GEN_ROAD:
4307 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4308 break;
4309 case ACTIVITY_CONVERT:
4310 s = t->sprites.unit.convert;
4311 break;
4312 default:
4313 break;
4316 if (s != NULL) {
4317 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4318 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4322 if (punit->ai_controlled && punit->activity != ACTIVITY_EXPLORE) {
4323 if (is_military_unit(punit)) {
4324 ADD_SPRITE_FULL(t->sprites.unit.auto_attack);
4325 } else {
4326 ADD_SPRITE_FULL(t->sprites.unit.auto_settler);
4330 if (unit_has_orders(punit)) {
4331 if (punit->orders.repeat) {
4332 ADD_SPRITE_FULL(t->sprites.unit.patrol);
4333 } else if (punit->activity != ACTIVITY_IDLE) {
4334 ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
4335 } else {
4336 ADD_SPRITE(t->sprites.unit.go_to, TRUE,
4337 FULL_TILE_X_OFFSET + t->activity_offset_x,
4338 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4342 if (t->sprites.unit.action_decision_want != NULL
4343 && should_ask_server_for_actions(punit)) {
4344 ADD_SPRITE(t->sprites.unit.action_decision_want, TRUE,
4345 FULL_TILE_X_OFFSET + t->activity_offset_x,
4346 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4349 if (punit->battlegroup != BATTLEGROUP_NONE) {
4350 ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
4353 if (t->sprites.unit.lowfuel
4354 && utype_fuel(ptype)
4355 && punit->fuel == 1
4356 && punit->moves_left <= 2 * SINGLE_MOVE) {
4357 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4358 ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
4360 if (t->sprites.unit.tired
4361 && punit->moves_left < SINGLE_MOVE
4362 && ptype->move_rate > 0) {
4363 /* Show a "tired" graphic if the unit has fewer than one move
4364 * remaining, except for units for which it's full movement. */
4365 ADD_SPRITE_FULL(t->sprites.unit.tired);
4368 if (stack || punit->client.occupied) {
4369 ADD_SPRITE_FULL(t->sprites.unit.stack);
4372 if (t->sprites.unit.vet_lev[punit->veteran]) {
4373 ADD_SPRITE_FULL(t->sprites.unit.vet_lev[punit->veteran]);
4376 ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
4377 ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
4378 ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
4380 return sprs - save_sprs;
4383 /**************************************************************************
4384 Add any corner road sprites to the sprite array.
4385 **************************************************************************/
4386 static int fill_road_corner_sprites(const struct tileset *t,
4387 const struct extra_type *pextra,
4388 struct drawn_sprite *sprs,
4389 bool road, bool *road_near,
4390 bool hider, bool *hider_near)
4392 struct drawn_sprite *saved_sprs = sprs;
4393 int i;
4394 int extra_idx = extra_index(pextra);
4396 if (is_cardinal_only_road(pextra)) {
4397 return 0;
4400 /* Roads going diagonally adjacent to this tile need to be
4401 * partly drawn on this tile. */
4403 /* Draw the corner sprite if:
4404 * - There is a diagonal road (not rail!) between two adjacent tiles.
4405 * - There is no diagonal road (not rail!) that intersects this road.
4406 * The logic is simple: roads are drawn underneath railrods, but are
4407 * not always covered by them (even in the corners!). But if a railroad
4408 * connects two tiles, only the railroad (no road) is drawn between
4409 * those tiles.
4411 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4412 enum direction8 dir = t->valid_tileset_dirs[i];
4414 if (!is_cardinal_tileset_dir(t, dir)) {
4415 /* Draw corner sprites for this non-cardinal direction. */
4416 int cw = (i + 1) % t->num_valid_tileset_dirs;
4417 int ccw
4418 = (i + t->num_valid_tileset_dirs - 1) % t->num_valid_tileset_dirs;
4419 enum direction8 cwdir = t->valid_tileset_dirs[cw];
4420 enum direction8 ccwdir = t->valid_tileset_dirs[ccw];
4422 if (t->sprites.extras[extra_idx].u.road.corner[dir]
4423 && (road_near[cwdir] && road_near[ccwdir]
4424 && !(hider_near[cwdir] && hider_near[ccwdir]))
4425 && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
4426 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.corner[dir]);
4431 return sprs - saved_sprs;
4434 /**************************************************************************
4435 Fill all road and rail sprites into the sprite array.
4436 **************************************************************************/
4437 static int fill_road_sprite_array(const struct tileset *t,
4438 const struct extra_type *pextra,
4439 struct drawn_sprite *sprs,
4440 bv_extras textras,
4441 bv_extras *textras_near,
4442 struct terrain *tterrain_near[8],
4443 const struct city *pcity)
4445 struct drawn_sprite *saved_sprs = sprs;
4446 bool road, road_near[8], hider, hider_near[8];
4447 bool land_near[8], hland_near[8];
4448 bool draw_road[8], draw_single_road;
4449 enum direction8 dir;
4450 int extra_idx = -1;
4451 bool cl = FALSE;
4452 enum extrastyle_id extrastyle;
4453 const struct road_type *proad = extra_road_get(pextra);
4455 extra_idx = extra_index(pextra);
4457 extrastyle = t->sprites.extras[extra_idx].extrastyle;
4459 if (extra_has_flag(pextra, EF_CONNECT_LAND)) {
4460 cl = TRUE;
4461 } else {
4462 int i;
4464 for (i = 0; i < 8; i++) {
4465 land_near[i] = FALSE;
4469 /* Fill some data arrays. rail_near and road_near store whether road/rail
4470 * is present in the given direction. draw_rail and draw_road store
4471 * whether road/rail is to be drawn in that direction. draw_single_road
4472 * and draw_single_rail store whether we need an isolated road/rail to be
4473 * drawn. */
4474 road = BV_ISSET(textras, extra_idx);
4476 hider = FALSE;
4477 extra_type_list_iterate(pextra->hiders, phider) {
4478 if (BV_ISSET(textras, extra_index(phider))) {
4479 hider = TRUE;
4480 break;
4482 } extra_type_list_iterate_end;
4484 if (road && (!pcity || !gui_options.draw_cities) && !hider) {
4485 draw_single_road = TRUE;
4486 } else {
4487 draw_single_road = FALSE;
4490 for (dir = 0; dir < 8; dir++) {
4491 bool roads_exist;
4493 /* Check if there is adjacent road/rail. */
4494 if (!is_cardinal_only_road(pextra)
4495 || is_cardinal_tileset_dir(t, dir)) {
4496 road_near[dir] = FALSE;
4497 extra_type_list_iterate(proad->integrators, iextra) {
4498 if (BV_ISSET(textras_near[dir], extra_index(iextra))) {
4499 road_near[dir] = TRUE;
4500 break;
4502 } extra_type_list_iterate_end;
4503 if (cl) {
4504 land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
4505 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN);
4507 } else {
4508 road_near[dir] = FALSE;
4509 land_near[dir] = FALSE;
4512 /* Draw rail/road if there is a connection from this tile to the
4513 * adjacent tile. But don't draw road if there is also a rail
4514 * connection. */
4515 roads_exist = road && (road_near[dir] || land_near[dir]);
4516 draw_road[dir] = roads_exist;
4517 hider_near[dir] = FALSE;
4518 hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
4519 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN;
4520 extra_type_list_iterate(pextra->hiders, phider) {
4521 bool hider_dir = FALSE;
4522 bool land_dir = FALSE;
4524 if (!is_cardinal_only_road(phider)
4525 || is_cardinal_tileset_dir(t, dir)) {
4526 if (BV_ISSET(textras_near[dir], extra_index(phider))) {
4527 hider_near[dir] = TRUE;
4528 hider_dir = TRUE;
4530 if (hland_near[dir]
4531 && is_extra_caused_by(phider, EC_ROAD)
4532 && extra_has_flag(phider, EF_CONNECT_LAND)) {
4533 land_dir = TRUE;
4535 if (hider_dir || land_dir) {
4536 if (BV_ISSET(textras, extra_index(phider))) {
4537 draw_road[dir] = FALSE;
4541 } extra_type_list_iterate_end;
4543 /* Don't draw an isolated road/rail if there's any connection.
4544 * draw_single_road would be true in the first place only if start tile has road,
4545 * so it will have road connection with any adjacent road tile. We check from real
4546 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
4547 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
4548 * draw single road in that case either. */
4549 if (draw_single_road && road_near[dir]) {
4550 draw_single_road = FALSE;
4554 /* Draw road corners */
4555 sprs
4556 += fill_road_corner_sprites(t, pextra, sprs, road, road_near, hider, hider_near);
4558 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
4559 /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
4560 * This means we only need a few sprites, but a lot of drawing is
4561 * necessary and it generally doesn't look very good. */
4562 int i;
4564 /* First draw roads under rails. */
4565 if (road) {
4566 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4567 if (draw_road[t->valid_tileset_dirs[i]]) {
4568 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.dir[i]);
4572 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4573 /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
4574 * road connections, one sprite for diagonal road connections.
4575 * This means we need about 4x more sprites than in style 0, but up to
4576 * 4x less drawing is needed. The drawing quality may also be
4577 * improved. */
4579 /* First draw roads under rails. */
4580 if (road) {
4581 int road_even_tileno = 0, road_odd_tileno = 0, i;
4583 for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
4584 enum direction8 even = t->valid_tileset_dirs[2 * i];
4585 enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
4587 if (draw_road[even]) {
4588 road_even_tileno |= 1 << i;
4590 if (draw_road[odd]) {
4591 road_odd_tileno |= 1 << i;
4595 /* Draw the cardinal/even roads first. */
4596 if (road_even_tileno != 0) {
4597 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.even[road_even_tileno]);
4599 if (road_odd_tileno != 0) {
4600 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.odd[road_odd_tileno]);
4603 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4604 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
4605 * entire finished tiles, with a bitwise index of the presence of
4606 * roads in each direction. */
4608 /* Draw roads first */
4609 if (road) {
4610 int road_tileno = 0, i;
4612 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4613 enum direction8 vdir = t->valid_tileset_dirs[i];
4615 if (draw_road[vdir]) {
4616 road_tileno |= 1 << i;
4620 if (road_tileno != 0 || draw_single_road) {
4621 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.total[road_tileno]);
4624 } else {
4625 fc_assert(FALSE);
4628 /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
4629 ESTYLE_ROAD_PARITY_COMBINED only). */
4630 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4631 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4632 if (draw_single_road) {
4633 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.isolated);
4637 return sprs - saved_sprs;
4640 /**************************************************************************
4641 Return the index of the sprite to be used for irrigation or farmland in
4642 this tile.
4644 We assume that the current tile has farmland or irrigation. We then
4645 choose a sprite (index) based upon which cardinally adjacent tiles have
4646 either farmland or irrigation (the two are considered interchangable for
4647 this).
4648 **************************************************************************/
4649 static int get_irrigation_index(const struct tileset *t,
4650 struct extra_type *pextra,
4651 bv_extras *textras_near)
4653 int tileno = 0, i;
4655 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4656 enum direction8 dir = t->cardinal_tileset_dirs[i];
4658 if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
4659 tileno |= 1 << i;
4663 return tileno;
4666 /**************************************************************************
4667 Fill in the farmland/irrigation sprite for the tile.
4668 **************************************************************************/
4669 static int fill_irrigation_sprite_array(const struct tileset *t,
4670 struct drawn_sprite *sprs,
4671 bv_extras textras,
4672 bv_extras *textras_near,
4673 const struct city *pcity)
4675 struct drawn_sprite *saved_sprs = sprs;
4677 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4678 * anyway, and ends up looking bad). */
4679 if (!(pcity && gui_options.draw_cities)) {
4680 extra_type_list_iterate(t->style_lists[ESTYLE_CARDINALS], pextra) {
4681 if (is_extra_drawing_enabled(pextra)) {
4682 int eidx = extra_index(pextra);
4684 if (BV_ISSET(textras, eidx)) {
4685 bool hidden = FALSE;
4687 extra_type_list_iterate(pextra->hiders, phider) {
4688 if (BV_ISSET(textras, extra_index(phider))) {
4689 hidden = TRUE;
4690 break;
4692 } extra_type_list_iterate_end;
4694 if (!hidden) {
4695 int idx = get_irrigation_index(t, pextra, textras_near);
4697 ADD_SPRITE_SIMPLE(t->sprites.extras[eidx].u.cardinals[idx]);
4701 } extra_type_list_iterate_end;
4704 return sprs - saved_sprs;
4707 /**************************************************************************
4708 Fill in the city overlays for the tile. This includes the citymap
4709 overlays on the mapview as well as the tile output sprites.
4710 **************************************************************************/
4711 static int fill_city_overlays_sprite_array(const struct tileset *t,
4712 struct drawn_sprite *sprs,
4713 const struct tile *ptile,
4714 const struct city *citymode)
4716 const struct city *pcity;
4717 const struct city *pwork;
4718 struct unit *psettler;
4719 struct drawn_sprite *saved_sprs = sprs;
4720 int city_x, city_y;
4721 const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
4723 if (NULL == ptile || TILE_UNKNOWN == client_tile_get_known(ptile)) {
4724 return 0;
4726 pwork = tile_worked(ptile);
4728 if (citymode) {
4729 pcity = citymode;
4730 } else {
4731 pcity = find_city_or_settler_near_tile(ptile, &psettler);
4734 /* Below code does not work if pcity is invisible.
4735 * Make sure it is not. */
4736 fc_assert_ret_val(pcity == NULL || pcity->tile != NULL, 0);
4737 if (pcity && !pcity->tile) {
4738 pcity = NULL;
4741 if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
4742 /* FIXME: check elsewhere for valid tile (instead of above) */
4744 if (!citymode && pcity->client.colored) {
4745 /* Add citymap overlay for a city. */
4746 int idx = pcity->client.color_index % NUM_CITY_COLORS;
4748 if (NULL != pwork && pwork == pcity) {
4749 ADD_SPRITE_SIMPLE(t->sprites.city.worked_tile_overlay.p[idx]);
4750 } else if (city_can_work_tile(pcity, ptile)) {
4751 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4753 } else if (NULL != pwork && pwork == pcity
4754 && (citymode || gui_options.draw_city_output)) {
4755 /* Add on the tile output sprites. */
4756 int food = city_tile_output_now(pcity, ptile, O_FOOD);
4757 int shields = city_tile_output_now(pcity, ptile, O_SHIELD);
4758 int trade = city_tile_output_now(pcity, ptile, O_TRADE);
4759 const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
4760 const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
4762 food = CLIP(0, food, NUM_TILES_DIGITS - 1);
4763 shields = CLIP(0, shields, NUM_TILES_DIGITS - 1);
4764 trade = CLIP(0, trade, NUM_TILES_DIGITS - 1);
4766 ADD_SPRITE(t->sprites.city.tile_foodnum[food], TRUE, ox, oy);
4767 ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
4768 ADD_SPRITE(t->sprites.city.tile_tradenum[trade], TRUE, ox, oy);
4770 } else if (psettler && psettler->client.colored) {
4771 /* Add citymap overlay for a unit. */
4772 int idx = psettler->client.color_index % NUM_CITY_COLORS;
4774 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4777 return sprs - saved_sprs;
4780 /****************************************************************************
4781 Helper function for fill_terrain_sprite_layer.
4782 Fill in the sprite array for blended terrain.
4783 ****************************************************************************/
4784 static int fill_terrain_sprite_blending(const struct tileset *t,
4785 struct drawn_sprite *sprs,
4786 const struct tile *ptile,
4787 const struct terrain *pterrain,
4788 struct terrain **tterrain_near)
4790 struct drawn_sprite *saved_sprs = sprs;
4791 const int W = t->normal_tile_width, H = t->normal_tile_height;
4792 const int offsets[4][2] = {
4793 {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4795 enum direction4 dir = 0;
4798 * We want to mark unknown tiles so that an unreal tile will be
4799 * given the same marking as our current tile - that way we won't
4800 * get the "unknown" dither along the edge of the map.
4802 for (; dir < 4; dir++) {
4803 struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
4804 struct terrain *other;
4806 if (!tile1
4807 || client_tile_get_known(tile1) == TILE_UNKNOWN
4808 || pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
4809 || (0 == t->sprites.drawing[terrain_index(other)]->blending
4810 && NULL == t->sprites.drawing[terrain_index(other)]->blender)) {
4811 continue;
4814 ADD_SPRITE(t->sprites.drawing[terrain_index(other)]->blend[dir], TRUE,
4815 offsets[dir][0], offsets[dir][1]);
4818 return sprs - saved_sprs;
4821 /****************************************************************************
4822 Add sprites for fog (and some forms of darkness).
4823 ****************************************************************************/
4824 static int fill_fog_sprite_array(const struct tileset *t,
4825 struct drawn_sprite *sprs,
4826 const struct tile *ptile,
4827 const struct tile_edge *pedge,
4828 const struct tile_corner *pcorner)
4830 struct drawn_sprite *saved_sprs = sprs;
4832 if (t->fogstyle == FOG_SPRITE && gui_options.draw_fog_of_war
4833 && NULL != ptile
4834 && TILE_KNOWN_UNSEEN == client_tile_get_known(ptile)) {
4835 /* With FOG_AUTO, fog is done this way. */
4836 ADD_SPRITE_SIMPLE(t->sprites.tx.fog);
4839 if (t->darkness_style == DARKNESS_CORNER && pcorner
4840 && gui_options.draw_fog_of_war) {
4841 int i, tileno = 0;
4843 for (i = 3; i >= 0; i--) {
4844 const int unknown = 0, fogged = 1, known = 2;
4845 int value = -1;
4847 if (!pcorner->tile[i]) {
4848 value = fogged;
4849 } else {
4850 switch (client_tile_get_known(pcorner->tile[i])) {
4851 case TILE_KNOWN_SEEN:
4852 value = known;
4853 break;
4854 case TILE_KNOWN_UNSEEN:
4855 value = fogged;
4856 break;
4857 case TILE_UNKNOWN:
4858 value = unknown;
4859 break;
4862 fc_assert(value >= 0 && value < 3);
4864 tileno = tileno * 3 + value;
4867 if (t->sprites.tx.fullfog[tileno]) {
4868 ADD_SPRITE_SIMPLE(t->sprites.tx.fullfog[tileno]);
4872 return sprs - saved_sprs;
4875 /****************************************************************************
4876 Helper function for fill_terrain_sprite_layer.
4877 ****************************************************************************/
4878 static int fill_terrain_sprite_array(struct tileset *t,
4879 struct drawn_sprite *sprs,
4880 int l, /* layer_num */
4881 const struct tile *ptile,
4882 const struct terrain *pterrain,
4883 struct terrain **tterrain_near,
4884 struct drawing_data *draw)
4886 struct drawn_sprite *saved_sprs = sprs;
4887 struct drawing_layer *dlp = &draw->layer[l];
4888 int this = dlp->match_index[0];
4889 int that = dlp->match_index[1];
4890 int ox = dlp->offset_x;
4891 int oy = dlp->offset_y;
4892 int i;
4894 #define MATCH(dir) \
4895 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4896 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4897 : -1)
4899 switch (dlp->sprite_type) {
4900 case CELL_WHOLE:
4902 switch (dlp->match_style) {
4903 case MATCH_NONE:
4905 int count = sprite_vector_size(&dlp->base);
4907 if (count > 0) {
4908 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4909 * to limit the number to a handleable size [0..32000). */
4910 count = fc_randomly(tile_index(ptile) % 32000, count);
4912 if (dlp->is_tall) {
4913 ox += FULL_TILE_X_OFFSET;
4914 oy += FULL_TILE_Y_OFFSET;
4916 ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
4918 break;
4920 case MATCH_SAME:
4922 int tileno = 0;
4924 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4925 enum direction8 dir = t->cardinal_tileset_dirs[i];
4927 if (MATCH(dir) == this) {
4928 tileno |= 1 << i;
4932 if (dlp->is_tall) {
4933 ox += FULL_TILE_X_OFFSET;
4934 oy += FULL_TILE_Y_OFFSET;
4936 ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
4937 break;
4939 case MATCH_PAIR:
4940 case MATCH_FULL:
4941 fc_assert(FALSE); /* not yet defined */
4942 break;
4944 break;
4946 case CELL_CORNER:
4948 /* Divide the tile up into four rectangular cells. Each of these
4949 * cells covers one corner, and each is adjacent to 3 different
4950 * tiles. For each cell we pick a sprite based upon the adjacent
4951 * terrains at each of those tiles. Thus, we have 8 different sprites
4952 * for each of the 4 cells (32 sprites total).
4954 * These arrays correspond to the direction4 ordering. */
4955 const int W = t->normal_tile_width;
4956 const int H = t->normal_tile_height;
4957 const int iso_offsets[4][2] = {
4958 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
4960 const int noniso_offsets[4][2] = {
4961 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
4964 /* put corner cells */
4965 for (i = 0; i < NUM_CORNER_DIRS; i++) {
4966 const int count = dlp->match_indices;
4967 int array_index = 0;
4968 enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
4969 int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
4970 int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
4971 int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
4972 struct sprite *s;
4974 /* synthesize 4 dimensional array? */
4975 switch (dlp->match_style) {
4976 case MATCH_NONE:
4977 /* We have no need for matching, just plug the piece in place. */
4978 break;
4979 case MATCH_SAME:
4980 array_index = array_index * 2 + (m[2] != this);
4981 array_index = array_index * 2 + (m[1] != this);
4982 array_index = array_index * 2 + (m[0] != this);
4983 break;
4984 case MATCH_PAIR:
4985 array_index = array_index * 2 + (m[2] == that);
4986 array_index = array_index * 2 + (m[1] == that);
4987 array_index = array_index * 2 + (m[0] == that);
4988 break;
4989 case MATCH_FULL:
4990 default:
4992 int n[3];
4993 int j = 0;
4994 for (; j < 3; j++) {
4995 int k = 0;
4996 for (; k < count; k++) {
4997 n[j] = k; /* default to last entry */
4998 if (m[j] == dlp->match_index[k])
5000 break;
5004 array_index = array_index * count + n[2];
5005 array_index = array_index * count + n[1];
5006 array_index = array_index * count + n[0];
5008 break;
5010 array_index = array_index * NUM_CORNER_DIRS + i;
5012 s = dlp->cells[array_index];
5013 if (s) {
5014 ADD_SPRITE(s, TRUE, x, y);
5017 break;
5020 #undef MATCH
5022 return sprs - saved_sprs;
5025 /****************************************************************************
5026 Helper function for fill_terrain_sprite_layer.
5027 Fill in the sprite array of darkness.
5028 ****************************************************************************/
5029 static int fill_terrain_sprite_darkness(struct tileset *t,
5030 struct drawn_sprite *sprs,
5031 const struct tile *ptile,
5032 struct terrain **tterrain_near)
5034 struct drawn_sprite *saved_sprs = sprs;
5035 int i, tileno;
5036 struct tile *adjc_tile;
5038 #define UNKNOWN(dir) \
5039 ((adjc_tile = mapstep(ptile, (dir))) \
5040 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
5042 switch (t->darkness_style) {
5043 case DARKNESS_NONE:
5044 break;
5045 case DARKNESS_ISORECT:
5046 for (i = 0; i < 4; i++) {
5047 const int W = t->normal_tile_width, H = t->normal_tile_height;
5048 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
5050 if (UNKNOWN(DIR4_TO_DIR8[i])) {
5051 ADD_SPRITE(t->sprites.tx.darkness[i], TRUE,
5052 offsets[i][0], offsets[i][1]);
5055 break;
5056 case DARKNESS_CARD_SINGLE:
5057 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5058 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5059 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[i]);
5062 break;
5063 case DARKNESS_CARD_FULL:
5064 /* We're looking to find the INDEX_NSEW for the directions that
5065 * are unknown. We want to mark unknown tiles so that an unreal
5066 * tile will be given the same marking as our current tile - that
5067 * way we won't get the "unknown" dither along the edge of the
5068 * map. */
5069 tileno = 0;
5070 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5071 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5072 tileno |= 1 << i;
5076 if (tileno != 0) {
5077 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[tileno]);
5079 break;
5080 case DARKNESS_CORNER:
5081 /* Handled separately. */
5082 break;
5084 #undef UNKNOWN
5086 return sprs - saved_sprs;
5089 /****************************************************************************
5090 Add sprites for the base tile to the sprite list. This doesn't
5091 include specials or rivers.
5092 ****************************************************************************/
5093 static int fill_terrain_sprite_layer(struct tileset *t,
5094 struct drawn_sprite *sprs,
5095 int layer_num,
5096 const struct tile *ptile,
5097 const struct terrain *pterrain,
5098 struct terrain **tterrain_near)
5100 struct sprite *sprite;
5101 struct drawn_sprite *saved_sprs = sprs;
5102 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
5103 const int l = (draw->is_reversed
5104 ? (draw->num_layers - layer_num - 1) : layer_num);
5106 fc_assert(layer_num < TERRAIN_LAYER_COUNT);
5108 /* Skip the normal drawing process. */
5109 /* FIXME: this should avoid calling load_sprite since it's slow and
5110 * increases the refcount without limit. */
5111 if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite,
5112 TRUE, FALSE))) {
5113 if (l == 0) {
5114 ADD_SPRITE_SIMPLE(sprite);
5115 return 1;
5116 } else {
5117 return 0;
5121 if (l < draw->num_layers) {
5122 sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
5124 if ((l + 1) == draw->blending) {
5125 sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
5129 return sprs - saved_sprs;
5132 /****************************************************************************
5133 Indicate whether a unit is to be drawn with a surrounding city outline
5134 under current conditions.
5135 (This includes being in focus, but if the caller has already checked that,
5136 they can bypass this slightly expensive check with check_focus == FALSE.)
5137 ****************************************************************************/
5138 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
5140 /* Display an outline for city-builder type units if they are selected,
5141 * and on a tile where a city can be built.
5142 * But suppress the outline if the unit has orders (likely it is in
5143 * transit to somewhere else and this will just slow down redraws). */
5144 return gui_options.draw_city_outlines
5145 && unit_is_cityfounder(punit)
5146 && !unit_has_orders(punit)
5147 && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN
5148 && city_can_be_built_here(unit_tile(punit), punit))
5149 && (!check_focus || unit_is_in_focus(punit));
5152 /****************************************************************************
5153 Fill in the grid sprites for the given tile, city, and unit.
5154 ****************************************************************************/
5155 static int fill_grid_sprite_array(const struct tileset *t,
5156 struct drawn_sprite *sprs,
5157 const struct tile *ptile,
5158 const struct tile_edge *pedge,
5159 const struct tile_corner *pcorner,
5160 const struct unit *punit,
5161 const struct city *pcity,
5162 const struct city *citymode)
5164 struct drawn_sprite *saved_sprs = sprs;
5166 if (pedge) {
5167 bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
5168 bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
5169 int i;
5170 struct unit_list *pfocus_units = get_units_in_focus();
5172 for (i = 0; i < NUM_EDGE_TILES; i++) {
5173 int dummy_x, dummy_y;
5174 const struct tile *tile = pedge->tile[i];
5175 struct player *powner = tile ? tile_owner(tile) : NULL;
5177 known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
5178 unit[i] = FALSE;
5179 if (tile && !citymode) {
5180 unit_list_iterate(pfocus_units, pfocus_unit) {
5181 if (unit_drawn_with_city_outline(pfocus_unit, FALSE)
5182 && city_tile_to_city_map(&dummy_x, &dummy_y,
5183 game.info.init_city_radius_sq,
5184 unit_tile(pfocus_unit), tile)) {
5185 unit[i] = TRUE;
5186 break;
5188 } unit_list_iterate_end;
5190 worked[i] = FALSE;
5192 city[i] = (tile
5193 && (NULL == powner || NULL == client.conn.playing
5194 || powner == client.conn.playing)
5195 && player_in_city_map(client.conn.playing, tile));
5196 if (city[i]) {
5197 if (citymode) {
5198 /* In citymode, we only draw worked tiles for this city - other
5199 * tiles may be marked as unavailable. */
5200 worked[i] = (tile_worked(tile) == citymode);
5201 } else {
5202 worked[i] = (NULL != tile_worked(tile));
5207 if (mapdeco_is_highlight_set(pedge->tile[0])
5208 || mapdeco_is_highlight_set(pedge->tile[1])) {
5209 ADD_SPRITE_SIMPLE(t->sprites.grid.selected[pedge->type]);
5210 } else if (!gui_options.draw_terrain && gui_options.draw_coastline
5211 && pedge->tile[0] && pedge->tile[1]
5212 && known[0] && known[1]
5213 && (is_ocean_tile(pedge->tile[0])
5214 ^ is_ocean_tile(pedge->tile[1]))) {
5215 ADD_SPRITE_SIMPLE(t->sprites.grid.coastline[pedge->type]);
5216 } else {
5217 if (gui_options.draw_map_grid) {
5218 if (worked[0] || worked[1]) {
5219 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5220 } else if (city[0] || city[1]) {
5221 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5222 } else if (known[0] || known[1]) {
5223 ADD_SPRITE_SIMPLE(t->sprites.grid.main[pedge->type]);
5226 if (gui_options.draw_city_outlines) {
5227 if (XOR(city[0], city[1])) {
5228 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5230 if (XOR(unit[0], unit[1])) {
5231 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5236 if (gui_options.draw_borders
5237 && BORDERS_DISABLED != game.info.borders
5238 && known[0]
5239 && known[1]) {
5240 struct player *owner0 = tile_owner(pedge->tile[0]);
5241 struct player *owner1 = tile_owner(pedge->tile[1]);
5243 if (owner0 != owner1) {
5244 if (owner0) {
5245 int plrid = player_index(owner0);
5246 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5247 [pedge->type][0]);
5249 if (owner1) {
5250 int plrid = player_index(owner1);
5251 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5252 [pedge->type][1]);
5256 } else if (NULL != ptile && TILE_UNKNOWN != client_tile_get_known(ptile)) {
5257 int cx, cy;
5259 if (citymode
5260 /* test to ensure valid coordinates? */
5261 && city_base_to_city_map(&cx, &cy, citymode, ptile)
5262 && !client_city_can_work_tile(citymode, ptile)) {
5263 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5266 if (gui_options.draw_native && citymode == NULL) {
5267 bool native = TRUE;
5268 struct unit_list *pfocus_units = get_units_in_focus();
5270 unit_list_iterate(pfocus_units, pfocus) {
5271 if (!is_native_tile(unit_type_get(pfocus), ptile)) {
5272 native = FALSE;
5273 break;
5275 } unit_list_iterate_end;
5277 if (!native) {
5278 if (t->sprites.grid.nonnative != NULL) {
5279 ADD_SPRITE_SIMPLE(t->sprites.grid.nonnative);
5280 } else {
5281 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5287 return sprs - saved_sprs;
5290 /****************************************************************************
5291 Fill in the given sprite array with any needed goto sprites.
5292 ****************************************************************************/
5293 static int fill_goto_sprite_array(const struct tileset *t,
5294 struct drawn_sprite *sprs,
5295 const struct tile *ptile,
5296 const struct tile_edge *pedge,
5297 const struct tile_corner *pcorner)
5299 struct drawn_sprite *saved_sprs = sprs;
5300 struct sprite *sprite;
5301 bool warn = FALSE;
5302 enum goto_tile_state state;
5303 int length;
5304 bool waypoint;
5306 if (goto_tile_state(ptile, &state, &length, &waypoint)) {
5307 if (length >= 0) {
5308 fc_assert(state >= 0);
5309 fc_assert(state < ARRAY_SIZE(t->sprites.path.s));
5311 sprite = t->sprites.path.s[state].specific;
5312 if (sprite != NULL) {
5313 ADD_SPRITE(sprite, FALSE, 0, 0);
5316 sprite = t->sprites.path.s[state].turns[length % 10];
5317 ADD_SPRITE_SIMPLE(sprite);
5318 if (length >= 10) {
5319 sprite = t->sprites.path.s[state].turns_tens[(length / 10) % 10];
5320 ADD_SPRITE_SIMPLE(sprite);
5321 if (length >= 100) {
5322 sprite = t->sprites.path.s[state].turns_hundreds[(length / 100)
5323 % 10];
5325 if (sprite != NULL) {
5326 ADD_SPRITE_SIMPLE(sprite);
5327 if (length >= 1000) {
5328 warn = TRUE;
5330 } else {
5331 warn = TRUE;
5337 if (waypoint) {
5338 ADD_SPRITE(t->sprites.path.waypoint, FALSE, 0, 0);
5341 if (warn) {
5342 /* Warn only once by tileset. */
5343 static char last_reported[256] = "";
5345 if (0 != strcmp(last_reported, t->name)) {
5346 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5347 "such as %d. Path not displayed as expected."),
5348 t->name, length);
5349 sz_strlcpy(last_reported, t->name);
5354 return sprs - saved_sprs;
5357 /****************************************************************************
5358 Should the given extra be drawn
5359 ****************************************************************************/
5360 static bool is_extra_drawing_enabled(struct extra_type *pextra)
5362 bool no_disable = TRUE; /* Draw if matches no cause */
5364 if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
5365 if (gui_options.draw_irrigation) {
5366 return TRUE;
5368 no_disable = FALSE;
5370 if (is_extra_caused_by(pextra, EC_POLLUTION)
5371 || is_extra_caused_by(pextra, EC_FALLOUT)) {
5372 if (gui_options.draw_pollution) {
5373 return TRUE;
5375 no_disable = FALSE;
5377 if (is_extra_caused_by(pextra, EC_MINE)) {
5378 if (gui_options.draw_mines) {
5379 return TRUE;
5381 no_disable = FALSE;
5383 if (is_extra_caused_by(pextra, EC_RESOURCE)) {
5384 if (gui_options.draw_specials) {
5385 return TRUE;
5387 no_disable = FALSE;
5389 if (is_extra_caused_by(pextra, EC_HUT)) {
5390 if (gui_options.draw_huts) {
5391 return TRUE;
5393 no_disable = FALSE;
5395 if (is_extra_caused_by(pextra, EC_BASE)) {
5396 if (gui_options.draw_fortress_airbase) {
5397 return TRUE;
5399 no_disable = FALSE;
5401 if (is_extra_caused_by(pextra, EC_ROAD)) {
5402 if (gui_options.draw_roads_rails) {
5403 return TRUE;
5405 no_disable = FALSE;
5408 return no_disable;
5411 /****************************************************************************
5412 Fill in the sprite array for the given tile, city, and unit.
5414 ptile, if specified, gives the tile. If specified the terrain and specials
5415 will be drawn for this tile. In this case (map_x,map_y) should give the
5416 location of the tile.
5418 punit, if specified, gives the unit. For tile drawing this should
5419 generally be get_drawable_unit(); otherwise it can be any unit.
5421 pcity, if specified, gives the city. For tile drawing this should
5422 generally be tile_city(ptile); otherwise it can be any city.
5424 citymode specifies whether this is part of a citydlg. If so some drawing
5425 is done differently.
5426 ****************************************************************************/
5427 int fill_sprite_array(struct tileset *t,
5428 struct drawn_sprite *sprs, enum mapview_layer layer,
5429 const struct tile *ptile,
5430 const struct tile_edge *pedge,
5431 const struct tile_corner *pcorner,
5432 const struct unit *punit, const struct city *pcity,
5433 const struct city *citymode,
5434 const struct unit_type *putype)
5436 int tileno, dir;
5437 bv_extras textras_near[8];
5438 bv_extras textras;
5439 struct terrain *tterrain_near[8];
5440 struct terrain *pterrain = NULL;
5441 struct drawn_sprite *save_sprs = sprs;
5442 struct player *owner = NULL;
5443 /* Unit drawing is disabled when the view options are turned off,
5444 * but only where we're drawing on the mapview. */
5445 bool do_draw_unit = (punit && (gui_options.draw_units || !ptile
5446 || (gui_options.draw_focus_unit
5447 && unit_is_in_focus(punit))));
5448 bool solid_bg = (gui_options.solid_color_behind_units
5449 && (do_draw_unit
5450 || (pcity && gui_options.draw_cities)
5451 || (ptile && !gui_options.draw_terrain)));
5453 if (citymode) {
5454 int count = 0, i, cx, cy;
5455 const struct tile *const *tiles = NULL;
5456 bool valid = FALSE;
5458 if (ptile) {
5459 tiles = &ptile;
5460 count = 1;
5461 } else if (pcorner) {
5462 tiles = pcorner->tile;
5463 count = NUM_CORNER_TILES;
5464 } else if (pedge) {
5465 tiles = pedge->tile;
5466 count = NUM_EDGE_TILES;
5469 for (i = 0; i < count; i++) {
5470 if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
5471 valid = TRUE;
5472 break;
5475 if (!valid) {
5476 return 0;
5480 if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
5481 textras = *tile_extras(ptile);
5482 pterrain = tile_terrain(ptile);
5484 if (NULL != pterrain) {
5485 if (layer == LAYER_TERRAIN1
5486 || layer == LAYER_TERRAIN2
5487 || layer == LAYER_TERRAIN3
5488 || layer == LAYER_WATER
5489 || layer == LAYER_ROADS) {
5490 build_tile_data(ptile, pterrain, tterrain_near, textras_near);
5492 } else {
5493 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
5494 TILE_XY(ptile));
5496 } else {
5497 BV_CLR_ALL(textras);
5500 switch (layer) {
5501 case LAYER_BACKGROUND:
5502 /* Set up background color. */
5503 if (gui_options.solid_color_behind_units) {
5504 if (do_draw_unit) {
5505 owner = unit_owner(punit);
5506 } else if (pcity && gui_options.draw_cities) {
5507 owner = city_owner(pcity);
5510 if (owner) {
5511 ADD_SPRITE_SIMPLE(t->sprites.player[player_index(owner)].background);
5512 } else if (ptile && !gui_options.draw_terrain) {
5513 ADD_SPRITE_SIMPLE(t->sprites.background.graphic);
5515 break;
5517 case LAYER_TERRAIN1:
5518 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5519 sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
5521 break;
5523 case LAYER_DARKNESS:
5524 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5525 sprs += fill_terrain_sprite_darkness(t, sprs, ptile, tterrain_near);
5527 break;
5529 case LAYER_TERRAIN2:
5530 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5531 sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
5533 break;
5535 case LAYER_TERRAIN3:
5536 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5537 fc_assert(MAX_NUM_LAYERS == 3);
5538 sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
5540 break;
5542 case LAYER_WATER:
5543 if (NULL != pterrain) {
5544 if (gui_options.draw_terrain && !solid_bg
5545 && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
5546 for (dir = 0; dir < t->num_cardinal_tileset_dirs; dir++) {
5547 int didx = t->cardinal_tileset_dirs[dir];
5549 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5550 int idx = extra_index(priver);
5552 if (BV_ISSET(textras_near[didx], idx)) {
5553 if (t->sprites.extras[idx].u.road.ru.rivers.outlet[dir] != NULL) {
5554 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.outlet[dir]);
5556 break;
5558 } extra_type_list_iterate_end;
5562 sprs += fill_irrigation_sprite_array(t, sprs, textras, textras_near,
5563 pcity);
5565 if (gui_options.draw_terrain && !solid_bg) {
5566 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5567 int idx = extra_index(priver);
5569 if (BV_ISSET(textras, idx)) {
5570 int i;
5572 /* Draw rivers on top of irrigation. */
5573 tileno = 0;
5574 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5575 enum direction8 cdir = t->cardinal_tileset_dirs[i];
5577 if (terrain_type_terrain_class(tterrain_near[cdir]) == TC_OCEAN
5578 || BV_ISSET(textras_near[cdir], idx)) {
5579 tileno |= 1 << i;
5583 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[tileno]);
5585 } extra_type_list_iterate_end;
5588 break;
5590 case LAYER_ROADS:
5591 if (NULL != pterrain) {
5592 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_SEPARATE], pextra) {
5593 if (is_extra_drawing_enabled(pextra)) {
5594 sprs += fill_road_sprite_array(t, pextra, sprs,
5595 textras, textras_near,
5596 tterrain_near, pcity);
5598 } extra_type_list_iterate_end;
5599 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_PARITY_COMBINED], pextra) {
5600 if (is_extra_drawing_enabled(pextra)) {
5601 sprs += fill_road_sprite_array(t, pextra, sprs,
5602 textras, textras_near,
5603 tterrain_near, pcity);
5605 } extra_type_list_iterate_end;
5606 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_COMBINED], pextra) {
5607 if (is_extra_drawing_enabled(pextra)) {
5608 sprs += fill_road_sprite_array(t, pextra, sprs,
5609 textras, textras_near,
5610 tterrain_near, pcity);
5612 } extra_type_list_iterate_end;
5614 break;
5616 case LAYER_SPECIAL1:
5617 if (NULL != pterrain) {
5618 if (ptile) {
5619 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5620 if (tile_has_extra(ptile, pextra)
5621 && is_extra_drawing_enabled(pextra)
5622 && t->sprites.extras[extra_index(pextra)].u.bmf.background) {
5623 bool hidden = FALSE;
5625 extra_type_list_iterate(pextra->hiders, phider) {
5626 if (BV_ISSET(textras, extra_index(phider))) {
5627 hidden = TRUE;
5628 break;
5630 } extra_type_list_iterate_end;
5632 if (!hidden) {
5633 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.background);
5636 } extra_type_list_iterate_end;
5639 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE1], pextra) {
5640 if (BV_ISSET(textras, extra_index(pextra))
5641 && is_extra_drawing_enabled(pextra)) {
5642 bool hidden = FALSE;
5644 extra_type_list_iterate(pextra->hiders, phider) {
5645 if (BV_ISSET(textras, extra_index(phider))) {
5646 hidden = TRUE;
5647 break;
5649 } extra_type_list_iterate_end;
5651 if (!hidden) {
5652 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5655 } extra_type_list_iterate_end;
5657 break;
5659 case LAYER_GRID1:
5660 if (t->type == TS_ISOMETRIC) {
5661 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5662 punit, pcity, citymode);
5664 break;
5666 case LAYER_CITY1:
5667 /* City. Some city sprites are drawn later. */
5668 if (pcity && gui_options.draw_cities) {
5669 if (!gui_options.draw_full_citybar && !gui_options.solid_color_behind_units) {
5670 ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
5671 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5672 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5674 /* For iso-view the city.wall graphics include the full city, whereas
5675 * for non-iso view they are an overlay on top of the base city
5676 * graphic. */
5677 if (t->type == TS_OVERHEAD || pcity->client.walls <= 0) {
5678 ADD_SPRITE(get_city_sprite(t->sprites.city.tile, pcity), TRUE,
5679 FULL_TILE_X_OFFSET + t->city_offset_x,
5680 FULL_TILE_Y_OFFSET + t->city_offset_y);
5682 if (t->type == TS_ISOMETRIC && pcity->client.walls > 0) {
5683 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5684 struct sprite *spr = NULL;
5686 if (cspr != NULL) {
5687 spr = get_city_sprite(cspr, pcity);
5689 if (spr == NULL) {
5690 cspr = t->sprites.city.single_wall;
5691 if (cspr != NULL) {
5692 spr = get_city_sprite(cspr, pcity);
5696 if (spr != NULL) {
5697 ADD_SPRITE(spr, TRUE,
5698 FULL_TILE_X_OFFSET + t->city_offset_x,
5699 FULL_TILE_Y_OFFSET + t->city_offset_y);
5702 if (!gui_options.draw_full_citybar && pcity->client.occupied) {
5703 ADD_SPRITE(get_city_sprite(t->sprites.city.occupied, pcity), TRUE,
5704 FULL_TILE_X_OFFSET + t->occupied_offset_x,
5705 FULL_TILE_Y_OFFSET + t->occupied_offset_y);
5707 if (t->type == TS_OVERHEAD && pcity->client.walls > 0) {
5708 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5709 struct sprite *spr = NULL;
5711 if (cspr != NULL) {
5712 spr = get_city_sprite(cspr, pcity);
5714 if (spr == NULL) {
5715 cspr = t->sprites.city.single_wall;
5716 if (cspr != NULL) {
5717 spr = get_city_sprite(cspr, pcity);
5721 if (spr != NULL) {
5722 ADD_SPRITE_FULL(spr);
5725 if (pcity->client.unhappy) {
5726 ADD_SPRITE_FULL(t->sprites.city.disorder);
5729 break;
5731 case LAYER_SPECIAL2:
5732 if (NULL != pterrain) {
5733 if (ptile) {
5734 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5735 if (tile_has_extra(ptile, pextra)
5736 && is_extra_drawing_enabled(pextra)
5737 && t->sprites.extras[extra_index(pextra)].u.bmf.middleground) {
5738 bool hidden = FALSE;
5740 extra_type_list_iterate(pextra->hiders, phider) {
5741 if (BV_ISSET(textras, extra_index(phider))) {
5742 hidden = TRUE;
5743 break;
5745 } extra_type_list_iterate_end;
5747 if (!hidden) {
5748 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.middleground);
5751 } extra_type_list_iterate_end;
5754 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE2], pextra) {
5755 if (BV_ISSET(textras, extra_index(pextra))
5756 && is_extra_drawing_enabled(pextra)) {
5757 bool hidden = FALSE;
5759 extra_type_list_iterate(pextra->hiders, phider) {
5760 if (BV_ISSET(textras, extra_index(phider))) {
5761 hidden = TRUE;
5762 break;
5764 } extra_type_list_iterate_end;
5766 if (!hidden) {
5767 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5770 } extra_type_list_iterate_end;
5772 break;
5774 case LAYER_UNIT:
5775 case LAYER_FOCUS_UNIT:
5776 if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
5777 bool stacked = ptile && (unit_list_size(ptile->units) > 1);
5778 bool backdrop = !pcity;
5780 if (ptile && unit_is_in_focus(punit)
5781 && t->sprites.unit.select[0]) {
5782 /* Special case for drawing the selection rectangle. The blinking
5783 * unit is handled separately, inside get_drawable_unit(). */
5784 ADD_SPRITE(t->sprites.unit.select[focus_unit_state], TRUE,
5785 t->select_offset_x, t->select_offset_y);
5788 sprs += fill_unit_sprite_array(t, sprs, punit, stacked, backdrop);
5789 } else if (putype != NULL && layer == LAYER_UNIT) {
5790 /* Only the sprite for the unit type. */
5791 sprs += fill_unit_type_sprite_array(t, sprs, putype,
5792 direction8_invalid());
5794 break;
5796 case LAYER_SPECIAL3:
5797 if (NULL != pterrain) {
5798 if (ptile) {
5799 bool show_flag = FALSE;
5800 struct player *eowner = extra_owner(ptile);
5802 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5803 if (is_extra_drawing_enabled(pextra)
5804 && tile_has_extra(ptile, pextra)
5805 && t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5806 bool hidden = FALSE;
5808 extra_type_list_iterate(pextra->hiders, phider) {
5809 if (BV_ISSET(textras, extra_index(phider))) {
5810 hidden = TRUE;
5811 break;
5813 } extra_type_list_iterate_end;
5815 if (!hidden) {
5816 if (t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5817 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.foreground);
5821 } extra_type_list_iterate_end;
5823 /* Show base flag. Not part of previous iteration as
5824 * "extras of ESTYLE_3_LAYER" != "bases" */
5825 if (eowner != NULL) {
5826 extra_type_list_iterate(t->flagged_bases_list, pextra) {
5827 if (tile_has_extra(ptile, pextra)) {
5828 bool hidden = FALSE;
5830 extra_type_list_iterate(pextra->hiders, phider) {
5831 if (BV_ISSET(textras, extra_index(phider))) {
5832 hidden = TRUE;
5833 break;
5835 } extra_type_list_iterate_end;
5837 if (!hidden) {
5838 show_flag = TRUE;
5841 } extra_type_list_iterate_end;
5843 if (show_flag) {
5844 ADD_SPRITE(get_nation_flag_sprite(t, nation_of_player(eowner)), TRUE,
5845 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5846 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5851 break;
5853 case LAYER_FOG:
5854 sprs += fill_fog_sprite_array(t, sprs, ptile, pedge, pcorner);
5855 break;
5857 case LAYER_CITY2:
5858 /* City size. Drawing this under fog makes it hard to read. */
5859 if (pcity && gui_options.draw_cities && !gui_options.draw_full_citybar) {
5860 bool warn = FALSE;
5862 ADD_SPRITE(t->sprites.city.size[city_size_get(pcity) % 10], FALSE,
5863 FULL_TILE_X_OFFSET + t->city_size_offset_x,
5864 FULL_TILE_Y_OFFSET + t->city_size_offset_y);
5865 if (10 <= city_size_get(pcity)) {
5866 ADD_SPRITE(t->sprites.city.size_tens[(city_size_get(pcity) / 10)
5867 % 10], FALSE,
5868 FULL_TILE_X_OFFSET + t->city_size_offset_x,
5869 FULL_TILE_Y_OFFSET + t->city_size_offset_y);
5870 if (100 <= city_size_get(pcity)) {
5871 struct sprite *sprite =
5872 t->sprites.city.size_hundreds[(city_size_get(pcity) / 100) % 10];
5874 if (NULL != sprite) {
5875 ADD_SPRITE(sprite, FALSE,
5876 FULL_TILE_X_OFFSET + t->city_size_offset_x,
5877 FULL_TILE_Y_OFFSET + t->city_size_offset_y);
5878 } else {
5879 warn = TRUE;
5881 if (1000 <= city_size_get(pcity)) {
5882 warn = TRUE;
5887 if (warn) {
5888 /* Warn only once by tileset. */
5889 static char last_reported[256] = "";
5891 if (0 != strcmp(last_reported, t->name)) {
5892 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5893 "such as %d. Size not displayed as expected."),
5894 t->name, city_size_get(pcity));
5895 sz_strlcpy(last_reported, t->name);
5899 break;
5901 case LAYER_GRID2:
5902 if (t->type == TS_OVERHEAD) {
5903 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5904 punit, pcity, citymode);
5906 break;
5908 case LAYER_OVERLAYS:
5909 sprs += fill_city_overlays_sprite_array(t, sprs, ptile, citymode);
5910 if (mapdeco_is_crosshair_set(ptile)) {
5911 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5913 break;
5915 case LAYER_CITYBAR:
5916 case LAYER_TILELABEL:
5917 /* Nothing. This is just a placeholder. */
5918 break;
5920 case LAYER_GOTO:
5921 if (ptile && goto_is_active()) {
5922 sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
5924 break;
5926 case LAYER_WORKERTASK:
5927 if (citymode != NULL && ptile != NULL) {
5928 worker_task_list_iterate(citymode->task_reqs, ptask) {
5929 if (ptask->ptile == ptile) {
5930 switch (ptask->act) {
5931 case ACTIVITY_MINE:
5932 if (ptask->tgt == NULL) {
5933 ADD_SPRITE_SIMPLE(t->sprites.unit.plant);
5934 } else {
5935 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5937 break;
5938 case ACTIVITY_IRRIGATE:
5939 if (ptask->tgt == NULL) {
5940 ADD_SPRITE_SIMPLE(t->sprites.unit.irrigate);
5941 } else {
5942 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5944 break;
5945 case ACTIVITY_GEN_ROAD:
5946 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(ptask->tgt)].activity);
5947 break;
5948 case ACTIVITY_TRANSFORM:
5949 ADD_SPRITE_SIMPLE(t->sprites.unit.transform);
5950 break;
5951 default:
5952 break;
5955 } worker_task_list_iterate_end;
5957 break;
5959 case LAYER_EDITOR:
5960 if (ptile && editor_is_active()) {
5961 if (editor_tile_is_selected(ptile)) {
5962 int color = 2 % tileset_num_city_colors(tileset);
5963 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
5966 if (NULL != map_startpos_get(ptile)) {
5967 /* FIXME: Use a more representative sprite. */
5968 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5971 break;
5973 case LAYER_COUNT:
5974 fc_assert(FALSE);
5975 break;
5978 return sprs - save_sprs;
5981 /**********************************************************************
5982 Set city tiles sprite values; should only happen after
5983 tilespec_load_tiles().
5984 ***********************************************************************/
5985 void tileset_setup_city_tiles(struct tileset *t, int style)
5987 if (style == game.control.styles_count - 1) {
5988 int i;
5990 /* Free old sprites */
5991 free_city_sprite(t->sprites.city.tile);
5993 for (i = 0; i < NUM_WALL_TYPES; i++) {
5994 free_city_sprite(t->sprites.city.wall[i]);
5995 t->sprites.city.wall[i] = NULL;
5997 free_city_sprite(t->sprites.city.single_wall);
5998 t->sprites.city.single_wall = NULL;
6000 free_city_sprite(t->sprites.city.occupied);
6002 t->sprites.city.tile = load_city_sprite(t, "city");
6004 for (i = 0; i < NUM_WALL_TYPES; i++) {
6005 char buffer[256];
6007 fc_snprintf(buffer, sizeof(buffer), "bldg_%d", i);
6008 t->sprites.city.wall[i] = load_city_sprite(t, buffer);
6010 t->sprites.city.single_wall = load_city_sprite(t, "wall");
6012 t->sprites.city.occupied = load_city_sprite(t, "occupied");
6014 for (style = 0; style < game.control.styles_count; style++) {
6015 if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
6016 tileset_error(LOG_FATAL, _("City style \"%s\": no city graphics."),
6017 city_style_rule_name(style));
6019 if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
6020 tileset_error(LOG_FATAL, _("City style \"%s\": no occupied graphics."),
6021 city_style_rule_name(style));
6027 /****************************************************************************
6028 Return the amount of time between calls to toggle_focus_unit_state.
6029 The main loop needs to call toggle_focus_unit_state about this often
6030 to do the active-unit animation.
6031 ****************************************************************************/
6032 double get_focus_unit_toggle_timeout(const struct tileset *t)
6034 if (t->sprites.unit.select[0]) {
6035 return 0.1;
6036 } else {
6037 return 0.5;
6041 /****************************************************************************
6042 Reset the focus unit state. This should be called when changing
6043 focus units.
6044 ****************************************************************************/
6045 void reset_focus_unit_state(struct tileset *t)
6047 focus_unit_state = 0;
6050 /****************************************************************************
6051 Setup tileset for showing combat where focus unit participates.
6052 ****************************************************************************/
6053 void focus_unit_in_combat(struct tileset *t)
6055 if (!t->sprites.unit.select[0]) {
6056 reset_focus_unit_state(t);
6060 /****************************************************************************
6061 Toggle/increment the focus unit state. This should be called once
6062 every get_focus_unit_toggle_timeout() seconds.
6063 ****************************************************************************/
6064 void toggle_focus_unit_state(struct tileset *t)
6066 focus_unit_state++;
6067 if (t->sprites.unit.select[0]) {
6068 focus_unit_state %= NUM_TILES_SELECT;
6069 } else {
6070 focus_unit_state %= 2;
6074 /**********************************************************************
6075 Find unit that we can display from given tile.
6076 ***********************************************************************/
6077 struct unit *get_drawable_unit(const struct tileset *t,
6078 struct tile *ptile,
6079 const struct city *citymode)
6081 struct unit *punit = find_visible_unit(ptile);
6083 if (punit == NULL) {
6084 return NULL;
6087 if (citymode && unit_owner(punit) == city_owner(citymode)) {
6088 return NULL;
6091 if (!unit_is_in_focus(punit)
6092 || t->sprites.unit.select[0] || focus_unit_state == 0) {
6093 return punit;
6094 } else {
6095 return NULL;
6099 /****************************************************************************
6100 This patch unloads all sprites from the sprite hash (the hash itself
6101 is left intact).
6102 ****************************************************************************/
6103 static void unload_all_sprites(struct tileset *t)
6105 if (t->sprite_hash) {
6106 sprite_hash_iterate(t->sprite_hash, tag_name, ss) {
6107 while (ss->ref_count > 0) {
6108 unload_sprite(t, tag_name);
6110 } sprite_hash_iterate_end;
6114 /**********************************************************************
6115 Free all sprites from tileset.
6116 ***********************************************************************/
6117 void tileset_free_tiles(struct tileset *t)
6119 int i;
6121 log_debug("tileset_free_tiles()");
6123 unload_all_sprites(t);
6125 free_city_sprite(t->sprites.city.tile);
6126 t->sprites.city.tile = NULL;
6128 for (i = 0; i < NUM_WALL_TYPES; i++) {
6129 free_city_sprite(t->sprites.city.wall[i]);
6130 t->sprites.city.wall[i] = NULL;
6132 free_city_sprite(t->sprites.city.single_wall);
6133 t->sprites.city.single_wall = NULL;
6135 free_city_sprite(t->sprites.city.occupied);
6136 t->sprites.city.occupied = NULL;
6138 if (t->sprite_hash) {
6139 sprite_hash_destroy(t->sprite_hash);
6140 t->sprite_hash = NULL;
6143 small_sprite_list_iterate(t->small_sprites, ss) {
6144 small_sprite_list_remove(t->small_sprites, ss);
6145 if (ss->file) {
6146 free(ss->file);
6148 fc_assert(ss->sprite == NULL);
6149 free(ss);
6150 } small_sprite_list_iterate_end;
6152 specfile_list_iterate(t->specfiles, sf) {
6153 specfile_list_remove(t->specfiles, sf);
6154 free(sf->file_name);
6155 if (sf->big_sprite) {
6156 free_sprite(sf->big_sprite);
6157 sf->big_sprite = NULL;
6159 free(sf);
6160 } specfile_list_iterate_end;
6162 sprite_vector_iterate(&t->sprites.city.worked_tile_overlay, psprite) {
6163 free_sprite(*psprite);
6164 } sprite_vector_iterate_end;
6165 sprite_vector_free(&t->sprites.city.worked_tile_overlay);
6167 sprite_vector_iterate(&t->sprites.city.unworked_tile_overlay, psprite) {
6168 free_sprite(*psprite);
6169 } sprite_vector_iterate_end;
6170 sprite_vector_free(&t->sprites.city.unworked_tile_overlay);
6172 if (t->sprites.tx.fullfog) {
6173 free(t->sprites.tx.fullfog);
6174 t->sprites.tx.fullfog = NULL;
6177 sprite_vector_free(&t->sprites.colors.overlays);
6178 sprite_vector_free(&t->sprites.explode.unit);
6179 sprite_vector_free(&t->sprites.nation_flag);
6180 sprite_vector_free(&t->sprites.nation_shield);
6181 sprite_vector_free(&t->sprites.citybar.occupancy);
6183 tileset_background_free(t);
6186 /**************************************************************************
6187 Return the sprite for drawing the given spaceship part.
6188 **************************************************************************/
6189 struct sprite *get_spaceship_sprite(const struct tileset *t,
6190 enum spaceship_part part)
6192 return t->sprites.spaceship[part];
6195 /**************************************************************************
6196 Return a sprite for the given citizen. The citizen's type is given,
6197 as well as their index (in the range [0..city_size_get(pcity))). The
6198 citizen's city can be used to determine which sprite to use (a NULL
6199 value indicates there is no city; i.e., the sprite is just being
6200 used as a picture).
6201 **************************************************************************/
6202 struct sprite *get_citizen_sprite(const struct tileset *t,
6203 enum citizen_category type,
6204 int citizen_index,
6205 const struct city *pcity)
6207 const struct citizen_graphic *graphic;
6208 int gfx_index = citizen_index;
6210 if (pcity != NULL) {
6211 gfx_index += pcity->client.first_citizen_index;
6214 if (type < CITIZEN_SPECIALIST) {
6215 fc_assert(type >= 0);
6216 graphic = &t->sprites.citizen[type];
6217 } else {
6218 fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
6219 graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
6222 if (graphic->count == 0) {
6223 return NULL;
6226 return graphic->sprite[gfx_index % graphic->count];
6229 /**************************************************************************
6230 Return the sprite for the nation.
6231 **************************************************************************/
6232 struct sprite *get_nation_flag_sprite(const struct tileset *t,
6233 const struct nation_type *pnation)
6235 return t->sprites.nation_flag.p[nation_index(pnation)];
6238 /**************************************************************************
6239 Return the shield sprite for the nation.
6240 **************************************************************************/
6241 struct sprite *get_nation_shield_sprite(const struct tileset *t,
6242 const struct nation_type *pnation)
6244 return t->sprites.nation_shield.p[nation_index(pnation)];
6247 /**************************************************************************
6248 Return the sprite for the technology/advance.
6249 **************************************************************************/
6250 struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
6252 fc_assert_ret_val(0 <= tech && tech < advance_count(), NULL);
6253 return t->sprites.tech[tech];
6256 /**************************************************************************
6257 Return the sprite for the building/improvement.
6258 **************************************************************************/
6259 struct sprite *get_building_sprite(const struct tileset *t,
6260 struct impr_type *pimprove)
6262 fc_assert_ret_val(NULL != pimprove, NULL);
6263 return t->sprites.building[improvement_index(pimprove)];
6266 /****************************************************************************
6267 Return the sprite for the government.
6268 ****************************************************************************/
6269 struct sprite *get_government_sprite(const struct tileset *t,
6270 const struct government *gov)
6272 fc_assert_ret_val(NULL != gov, NULL);
6273 return t->sprites.government[government_index(gov)];
6276 /****************************************************************************
6277 Return the sprite for the unit type (the base "unit" sprite).
6278 If 'facing' is direction8_invalid(), will use an unoriented sprite or
6279 a default orientation.
6280 ****************************************************************************/
6281 struct sprite *get_unittype_sprite(const struct tileset *t,
6282 const struct unit_type *punittype,
6283 enum direction8 facing)
6285 int uidx = utype_index(punittype);
6286 bool icon = !direction8_is_valid(facing);
6288 fc_assert_ret_val(NULL != punittype, NULL);
6290 if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
6291 facing = t->unit_default_orientation;
6292 /* May not have been specified, but it only matters if we don't
6293 * turn out to have an icon sprite */
6296 if (t->sprites.units.icon[uidx]
6297 && (icon || t->sprites.units.facing[uidx][facing] == NULL)) {
6298 /* Has icon sprite, and we prefer to (or must) use it */
6299 return t->sprites.units.icon[uidx];
6300 } else {
6301 /* We should have a valid orientation by now. Failure to have either
6302 * an icon sprite or default orientation should have been caught at
6303 * tileset load. */
6304 fc_assert_ret_val(direction8_is_valid(facing), NULL);
6305 return t->sprites.units.facing[uidx][facing];
6309 /**************************************************************************
6310 Return a "sample" sprite for this city style.
6311 **************************************************************************/
6312 struct sprite *get_sample_city_sprite(const struct tileset *t,
6313 int style_idx)
6315 int num_thresholds =
6316 t->sprites.city.tile->styles[style_idx].land_num_thresholds;
6318 if (num_thresholds == 0) {
6319 return NULL;
6320 } else {
6321 return (t->sprites.city.tile->styles[style_idx]
6322 .land_thresholds[num_thresholds - 1].sprite);
6326 /**************************************************************************
6327 Return a sprite with an "arrow" theme graphic.
6328 **************************************************************************/
6329 struct sprite *get_arrow_sprite(const struct tileset *t,
6330 enum arrow_type arrow)
6332 fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, NULL);
6334 return t->sprites.arrow[arrow];
6337 /**************************************************************************
6338 Return a tax sprite for the given output type (usually gold/lux/sci).
6339 **************************************************************************/
6340 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype)
6342 switch (otype) {
6343 case O_SCIENCE:
6344 return t->sprites.tax_science;
6345 case O_GOLD:
6346 return t->sprites.tax_gold;
6347 case O_LUXURY:
6348 return t->sprites.tax_luxury;
6349 case O_TRADE:
6350 case O_FOOD:
6351 case O_SHIELD:
6352 case O_LAST:
6353 break;
6355 return NULL;
6358 /**************************************************************************
6359 Return event icon sprite
6360 **************************************************************************/
6361 struct sprite *get_event_sprite(const struct tileset *t, enum event_type event)
6363 return t->sprites.events[event];
6366 /**************************************************************************
6367 Return a thumbs-up/thumbs-down sprite to show treaty approval or
6368 disapproval.
6369 **************************************************************************/
6370 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
6372 return t->sprites.treaty_thumb[on_off ? 1 : 0];
6375 /**************************************************************************
6376 Return a sprite_vector containing the animation sprites for a unit
6377 explosion.
6378 **************************************************************************/
6379 const struct sprite_vector *get_unit_explode_animation(const struct
6380 tileset *t)
6382 return &t->sprites.explode.unit;
6385 /****************************************************************************
6386 Return a sprite contining the single nuke graphic.
6388 TODO: This should be an animation like the unit explode animation.
6389 ****************************************************************************/
6390 struct sprite *get_nuke_explode_sprite(const struct tileset *t)
6392 return t->sprites.explode.nuke;
6395 /**************************************************************************
6396 Return all the sprites used for city bar drawing.
6397 **************************************************************************/
6398 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
6400 if (gui_options.draw_full_citybar) {
6401 return &t->sprites.citybar;
6402 } else {
6403 return NULL;
6407 /**************************************************************************
6408 Return all the sprites used for editor icons, images, etc.
6409 **************************************************************************/
6410 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
6412 return &t->sprites.editor;
6415 /**************************************************************************
6416 Returns a sprite for the given cursor. The "hot" coordinates (the
6417 active coordinates of the mouse relative to the sprite) are placed int
6418 (*hot_x, *hot_y).
6419 A cursor can consist of several frames to be used for animation.
6420 **************************************************************************/
6421 struct sprite *get_cursor_sprite(const struct tileset *t,
6422 enum cursor_type cursor,
6423 int *hot_x, int *hot_y, int frame)
6425 *hot_x = t->sprites.cursor[cursor].hot_x;
6426 *hot_y = t->sprites.cursor[cursor].hot_y;
6427 return t->sprites.cursor[cursor].frame[frame];
6430 /****************************************************************************
6431 Return a sprite for the given icon. Icons are used by the operating
6432 system/window manager. Usually freeciv has to tell the OS what icon to
6433 use.
6435 Note that this function will return NULL before the sprites are loaded.
6436 The GUI code must be sure to call tileset_load_tiles before setting the
6437 top-level icon.
6438 ****************************************************************************/
6439 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
6441 return t->sprites.icon[icon];
6444 /****************************************************************************
6445 Returns a sprite with the "user-attention" crosshair graphic.
6447 FIXME: This function shouldn't be needed if the attention graphics are
6448 drawn natively by the tileset code.
6449 ****************************************************************************/
6450 struct sprite *get_attention_crosshair_sprite(const struct tileset *t)
6452 return t->sprites.user.attention;
6455 /****************************************************************************
6456 Returns a sprite for the given indicator with the given index. The
6457 index should be in [0, NUM_TILES_PROGRESS).
6458 ****************************************************************************/
6459 struct sprite *get_indicator_sprite(const struct tileset *t,
6460 enum indicator_type indicator,
6461 int idx)
6463 idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
6465 fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, NULL);
6467 return t->sprites.indicator[indicator][idx];
6470 /****************************************************************************
6471 Return a sprite for the unhappiness of the unit - to be shown as an
6472 overlay on the unit in the city support dialog, for instance.
6474 May return NULL if there's no unhappiness.
6475 ****************************************************************************/
6476 struct sprite *get_unit_unhappy_sprite(const struct tileset *t,
6477 const struct unit *punit,
6478 int happy_cost)
6480 const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
6482 if (unhappy > 0) {
6483 return t->sprites.upkeep.unhappy[unhappy - 1];
6484 } else {
6485 return NULL;
6489 /****************************************************************************
6490 Return a sprite for the upkeep of the unit - to be shown as an overlay
6491 on the unit in the city support dialog, for instance.
6493 May return NULL if there's no upkeep of the kind.
6494 ****************************************************************************/
6495 struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
6496 Output_type_id otype,
6497 const struct unit *punit,
6498 const int *upkeep_cost)
6500 const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES + 1);
6502 if (upkeep > 0) {
6503 return t->sprites.upkeep.output[otype][upkeep - 1];
6504 } else {
6505 return NULL;
6509 /****************************************************************************
6510 Return a rectangular sprite containing a fog "color". This can be used
6511 for drawing fog onto arbitrary areas (like the overview).
6512 ****************************************************************************/
6513 struct sprite *get_basic_fog_sprite(const struct tileset *t)
6515 return t->sprites.tx.fog;
6518 /****************************************************************************
6519 Return the tileset's color system.
6520 ****************************************************************************/
6521 struct color_system *get_color_system(const struct tileset *t)
6523 return t->color_system;
6526 /****************************************************************************
6527 Loads preferred theme if there's any.
6528 ****************************************************************************/
6529 void tileset_use_preferred_theme(const struct tileset *t)
6531 char *default_theme_name = NULL;
6532 size_t default_theme_name_sz = 0;
6533 int i;
6535 switch (get_gui_type()) {
6536 case GUI_GTK2:
6537 default_theme_name = gui_options.gui_gtk2_default_theme_name;
6538 default_theme_name_sz = sizeof(gui_options.gui_gtk2_default_theme_name);
6539 break;
6540 case GUI_GTK3:
6541 default_theme_name = gui_options.gui_gtk3_default_theme_name;
6542 default_theme_name_sz = sizeof(gui_options.gui_gtk3_default_theme_name);
6543 break;
6544 case GUI_GTK3_22:
6545 default_theme_name = gui_options.gui_gtk3_22_default_theme_name;
6546 default_theme_name_sz = sizeof(gui_options.gui_gtk3_22_default_theme_name);
6547 break;
6548 case GUI_GTK3x:
6549 default_theme_name = gui_options.gui_gtk4_default_theme_name;
6550 default_theme_name_sz = sizeof(gui_options.gui_gtk4_default_theme_name);
6551 case GUI_SDL2:
6552 default_theme_name = gui_options.gui_sdl2_default_theme_name;
6553 default_theme_name_sz = sizeof(gui_options.gui_sdl2_default_theme_name);
6554 break;
6555 case GUI_STUB:
6556 case GUI_QT:
6557 case GUI_SDL:
6558 case GUI_WEB:
6559 break;
6562 if (NULL == default_theme_name || 0 == default_theme_name_sz) {
6563 /* Theme is not supported by this client. */
6564 return;
6567 for (i = 0; i < t->num_preferred_themes; i++) {
6568 if (strcmp(t->preferred_themes[i], default_theme_name)) {
6569 if (popup_theme_suggestion_dialog(t->preferred_themes[i])) {
6570 log_debug("trying theme \"%s\".", t->preferred_themes[i]);
6571 if (load_theme(t->preferred_themes[i])) {
6572 (void) fc_strlcpy(default_theme_name, t->preferred_themes[i],
6573 default_theme_name_sz);
6574 return;
6579 log_verbose("The tileset doesn't specify preferred themes or none of its "
6580 "preferred themes can be used. Using system default.");
6581 gui_clear_theme();
6584 /****************************************************************************
6585 Initialize tileset structure
6586 ****************************************************************************/
6587 void tileset_init(struct tileset *t)
6589 int wi;
6591 /* We currently have no city sprites loaded. */
6592 t->sprites.city.tile = NULL;
6594 for (wi = 0; wi < NUM_WALL_TYPES; wi++) {
6595 t->sprites.city.wall[wi] = NULL;
6597 t->sprites.city.single_wall = NULL;
6599 t->sprites.city.occupied = NULL;
6601 t->sprites.background.color = NULL;
6602 t->sprites.background.graphic = NULL;
6604 player_slots_iterate(pslot) {
6605 int edge, j, id = player_slot_index(pslot);
6607 for (edge = 0; edge < EDGE_COUNT; edge++) {
6608 for (j = 0; j < 2; j++) {
6609 t->sprites.player[id].grid_borders[edge][j] = NULL;
6613 t->sprites.player[id].color = NULL;
6614 t->sprites.player[id].background = NULL;
6615 } player_slots_iterate_end;
6617 t->max_upkeep_height = 0;
6620 /****************************************************************************
6621 Fill the sprite array with sprites that together make a representative
6622 image of the given terrain type. Suitable for use as an icon and in list
6623 views.
6625 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
6626 Using other values for 'layer' here will result in undefined behaviour. ;)
6627 ****************************************************************************/
6628 int fill_basic_terrain_layer_sprite_array(struct tileset *t,
6629 struct drawn_sprite *sprs,
6630 int layer,
6631 struct terrain *pterrain)
6633 struct drawn_sprite *save_sprs = sprs;
6634 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
6636 struct terrain *tterrain_near[8];
6637 bv_special tspecial_near[8];
6639 struct tile dummy_tile; /* :( */
6641 int i;
6644 memset(&dummy_tile, 0, sizeof(struct tile));
6646 for (i = 0; i < 8; i++) {
6647 tterrain_near[i] = pterrain;
6648 BV_CLR_ALL(tspecial_near[i]);
6651 i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
6652 sprs += fill_terrain_sprite_array(t, sprs, i, &dummy_tile,
6653 pterrain, tterrain_near, draw);
6655 return sprs - save_sprs;
6658 /****************************************************************************
6659 Return the sprite for the given resource type.
6660 ****************************************************************************/
6661 struct sprite *get_resource_sprite(const struct tileset *t,
6662 const struct resource_type *presource)
6664 if (presource == NULL) {
6665 return NULL;
6668 return t->sprites.extras[presource->self->id].u.single;
6671 /****************************************************************************
6672 Return a representative sprite for the given extra type.
6673 ****************************************************************************/
6674 int fill_basic_extra_sprite_array(const struct tileset *t,
6675 struct drawn_sprite *sprs,
6676 const struct extra_type *pextra)
6678 int idx = extra_index(pextra);
6679 struct drawn_sprite *saved_sprs = sprs;
6681 switch (t->sprites.extras[idx].extrastyle) {
6682 case ESTYLE_SINGLE1:
6683 case ESTYLE_SINGLE2:
6684 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.single);
6685 break;
6686 case ESTYLE_CARDINALS:
6687 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.cardinals[0]);
6688 break;
6689 case ESTYLE_ROAD_ALL_SEPARATE:
6690 case ESTYLE_ROAD_PARITY_COMBINED:
6691 case ESTYLE_ROAD_ALL_COMBINED:
6692 case ESTYLE_RIVER:
6693 return fill_basic_road_sprite_array(t, sprs, pextra);
6694 case ESTYLE_3LAYER:
6695 return fill_basic_base_sprite_array(t, sprs, pextra);
6696 case ESTYLE_COUNT:
6697 fc_assert(t->sprites.extras[idx].extrastyle != ESTYLE_COUNT);
6698 break;
6701 return sprs - saved_sprs;
6704 /****************************************************************************
6705 Fills the sprite array with sprites that together make a representative
6706 image of the given road type. The image is suitable for use as an icon
6707 for the road type, for example.
6708 ****************************************************************************/
6709 int fill_basic_road_sprite_array(const struct tileset *t,
6710 struct drawn_sprite *sprs,
6711 const struct extra_type *pextra)
6713 struct drawn_sprite *saved_sprs = sprs;
6714 int idx;
6715 int i;
6716 enum extrastyle_id extrastyle;
6718 if (!t || !sprs || !pextra) {
6719 return 0;
6722 idx = extra_index(pextra);
6724 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6725 return 0;
6728 extrastyle = t->sprites.extras[idx].extrastyle;
6730 if (extrastyle == ESTYLE_RIVER) {
6731 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[0]);
6732 } else {
6733 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
6734 if (!t->valid_tileset_dirs[i]) {
6735 continue;
6737 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
6738 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.dir[i]);
6739 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
6740 if ((i % 2) == 0) {
6741 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.combo.even[1 << (i / 2)]);
6743 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
6744 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.total[1 << i]);
6749 return sprs - saved_sprs;
6752 /****************************************************************************
6753 Fills the sprite array with sprites that together make a representative
6754 image of the given base type. The image is suitable for use as an icon
6755 for the base type, for example.
6756 ****************************************************************************/
6757 int fill_basic_base_sprite_array(const struct tileset *t,
6758 struct drawn_sprite *sprs,
6759 const struct extra_type *pextra)
6761 struct drawn_sprite *saved_sprs = sprs;
6762 int idx;
6764 if (!t || !sprs || !pextra) {
6765 return 0;
6768 idx = extra_index(pextra);
6770 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6771 return 0;
6774 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
6775 if ((x) != NULL) {\
6776 ADD_SPRITE_FULL(x);\
6778 } while (0)
6780 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
6781 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.background);
6782 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.middleground);
6783 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.foreground);
6785 #undef ADD_SPRITE_IF_NOT_NULL
6787 return sprs - saved_sprs;
6790 /****************************************************************************
6791 Gets the nth layer of the tileset.
6792 ****************************************************************************/
6793 enum mapview_layer tileset_get_layer(const struct tileset *t, int n)
6795 fc_assert(n < LAYER_COUNT);
6796 return t->layer_order[n];
6799 /****************************************************************************
6800 Gets the nth layer of the tileset.
6801 ****************************************************************************/
6802 bool tileset_layer_in_category(enum mapview_layer layer,
6803 enum layer_category cat)
6805 switch (layer) {
6806 case LAYER_BACKGROUND:
6807 case LAYER_TERRAIN1:
6808 case LAYER_DARKNESS:
6809 case LAYER_TERRAIN2:
6810 case LAYER_TERRAIN3:
6811 case LAYER_WATER:
6812 case LAYER_ROADS:
6813 case LAYER_SPECIAL1:
6814 case LAYER_SPECIAL2:
6815 case LAYER_SPECIAL3:
6816 return cat == LAYER_CATEGORY_CITY || cat == LAYER_CATEGORY_TILE;
6817 case LAYER_CITY1:
6818 case LAYER_CITY2:
6819 return cat == LAYER_CATEGORY_CITY;
6820 case LAYER_UNIT:
6821 case LAYER_FOCUS_UNIT:
6822 return cat == LAYER_CATEGORY_UNIT;
6823 case LAYER_GRID1:
6824 case LAYER_FOG:
6825 case LAYER_GRID2:
6826 case LAYER_OVERLAYS:
6827 case LAYER_TILELABEL:
6828 case LAYER_CITYBAR:
6829 case LAYER_GOTO:
6830 case LAYER_WORKERTASK:
6831 case LAYER_EDITOR:
6832 return FALSE;
6833 case LAYER_COUNT:
6834 break; /* and fail below */
6837 fc_assert_msg(FALSE, "Unknown layer category: %d", cat);
6838 return FALSE;
6841 /****************************************************************************
6842 Setup tiles for one player using the player color.
6843 ****************************************************************************/
6844 void tileset_player_init(struct tileset *t, struct player *pplayer)
6846 int plrid, i, j;
6847 struct sprite *color;
6849 fc_assert_ret(pplayer != NULL);
6851 plrid = player_index(pplayer);
6852 fc_assert_ret(plrid >= 0);
6853 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6855 /* Free all data before recreating it. */
6856 tileset_player_free(t, plrid);
6858 if (player_has_color(t, pplayer)) {
6859 t->sprites.player[plrid].color = color
6860 = create_plr_sprite(get_player_color(t, pplayer));
6861 } else {
6862 /* XXX: if player hasn't been assigned a color, perhaps there's no
6863 * point proceeding with an arbitrary color; this should only happen
6864 * in pregame. Probably blank sprites would be better. */
6866 fc_assert_ret(t->sprites.background.color != NULL);
6868 color = t->sprites.background.color;
6871 t->sprites.player[plrid].background
6872 = crop_sprite(color, 0, 0,
6873 t->normal_tile_width, t->normal_tile_height,
6874 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6876 for (i = 0; i < EDGE_COUNT; i++) {
6877 for (j = 0; j < 2; j++) {
6878 struct sprite *s;
6880 if (color && t->sprites.grid.borders[i][j]) {
6881 s = crop_sprite(color, 0, 0,
6882 t->normal_tile_width, t->normal_tile_height,
6883 t->sprites.grid.borders[i][j], 0, 0, 1.0f, FALSE);
6884 } else {
6885 s = t->sprites.grid.borders[i][j];
6887 t->sprites.player[plrid].grid_borders[i][j] = s;
6892 /****************************************************************************
6893 Free tiles for one player using the player color.
6894 ****************************************************************************/
6895 static void tileset_player_free(struct tileset *t, int plrid)
6897 int i, j;
6899 fc_assert_ret(plrid >= 0);
6900 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6902 if (t->sprites.player[plrid].color) {
6903 free_sprite(t->sprites.player[plrid].color);
6904 t->sprites.player[plrid].color = NULL;
6906 if (t->sprites.player[plrid].background) {
6907 free_sprite(t->sprites.player[plrid].background);
6908 t->sprites.player[plrid].background = NULL;
6911 for (i = 0; i < EDGE_COUNT; i++) {
6912 for (j = 0; j < 2; j++) {
6913 if (t->sprites.player[plrid].grid_borders[i][j]) {
6914 free_sprite(t->sprites.player[plrid].grid_borders[i][j]);
6915 t->sprites.player[plrid].grid_borders[i][j] = NULL;
6921 /****************************************************************************
6922 Setup tiles for the background.
6923 ****************************************************************************/
6924 void tileset_background_init(struct tileset *t)
6926 /* Free all data before recreating it. */
6927 tileset_background_free(t);
6929 /* generate background color */
6930 t->sprites.background.color
6931 = create_plr_sprite(ensure_color(game.plr_bg_color));
6933 /* Chop up and build the background graphics. */
6934 t->sprites.background.graphic
6935 = crop_sprite(t->sprites.background.color, 0, 0,
6936 t->normal_tile_width, t->normal_tile_height,
6937 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6940 /****************************************************************************
6941 Free tiles for the background.
6942 ****************************************************************************/
6943 void tileset_background_free(struct tileset *t)
6945 if (t->sprites.background.color) {
6946 free_sprite(t->sprites.background.color);
6947 t->sprites.background.color = NULL;
6950 if (t->sprites.background.graphic) {
6951 free_sprite(t->sprites.background.graphic);
6952 t->sprites.background.graphic = NULL;
6956 /****************************************************************************
6957 Reset tileset data specific to ruleset.
6958 ****************************************************************************/
6959 void tileset_ruleset_reset(struct tileset *t)
6961 int i;
6963 for (i = 0; i < ESTYLE_COUNT; i++) {
6964 if (t->style_lists[i] != NULL) {
6965 extra_type_list_destroy(t->style_lists[i]);
6966 t->style_lists[i] = extra_type_list_new();
6970 if (t->flagged_bases_list != NULL) {
6971 extra_type_list_destroy(t->flagged_bases_list);
6972 t->flagged_bases_list = extra_type_list_new();
6976 /****************************************************************************
6977 Is tileset in sane state?
6978 ****************************************************************************/
6979 bool tileset_is_fully_loaded(void)
6981 return !tileset_update;
6984 /****************************************************************************
6985 Return tileset name
6986 ****************************************************************************/
6987 const char *tileset_name_get(struct tileset *t)
6989 return t->given_name;
6992 /****************************************************************************
6993 Return tileset version
6994 ****************************************************************************/
6995 const char *tileset_version(struct tileset *t)
6997 return t->version;
7000 /****************************************************************************
7001 Return tileset description summary
7002 ****************************************************************************/
7003 const char *tileset_summary(struct tileset *t)
7005 return t->summary;
7008 /****************************************************************************
7009 Return tileset description body
7010 ****************************************************************************/
7011 const char *tileset_description(struct tileset *t)
7013 return t->description;
7016 /****************************************************************************
7017 Return what ruleset this tileset is primarily meant for
7018 ****************************************************************************/
7019 char *tileset_what_ruleset(struct tileset *t)
7021 return t->for_ruleset;
7024 /****************************************************************************
7025 Return tileset topology index
7026 ****************************************************************************/
7027 int tileset_topo_index(struct tileset *t)
7029 return t->ts_topo_idx;