Updated Scottish Gaelic localisation from Michael Bauer
[freeciv.git] / client / tilespec.c
blob2edf5154474e827ed0a22344bd98992877f33043
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 "fcintl.h"
34 #include "log.h"
35 #include "mem.h"
36 #include "rand.h"
37 #include "registry.h"
38 #include "shared.h"
39 #include "string_vector.h"
40 #include "support.h"
42 /* common */
43 #include "base.h"
44 #include "effects.h"
45 #include "game.h" /* game.control.styles_count */
46 #include "government.h"
47 #include "map.h"
48 #include "movement.h"
49 #include "nation.h"
50 #include "player.h"
51 #include "road.h"
52 #include "specialist.h"
53 #include "unit.h"
54 #include "unitlist.h"
56 /* client/include */
57 #include "dialogs_g.h"
58 #include "graphics_g.h"
59 #include "gui_main_g.h"
60 #include "mapview_g.h" /* for update_map_canvas_visible */
61 #include "menu_g.h"
62 #include "themes_g.h"
64 /* client */
65 #include "citydlg_common.h" /* for generate_citydlg_dimensions() */
66 #include "client_main.h"
67 #include "climap.h" /* for client_tile_get_known() */
68 #include "colors_common.h"
69 #include "control.h" /* for fill_xxx */
70 #include "editor.h"
71 #include "goto.h"
72 #include "options.h" /* for fill_xxx */
73 #include "themes_common.h"
75 #include "tilespec.h"
77 #define TILESPEC_CAPSTR "+Freeciv-2.5-tilespec duplicates_ok"
79 * Tilespec capabilities acceptable to this program:
81 * +Freeciv-2.4-tilespec
82 * - basic format for Freeciv versions 2.4.x; required
84 * +Freeciv-tilespec-Devel-YYYY.MMM.DD
85 * - tilespec of the development version at the given data
87 * duplicates_ok
88 * - we can handle existence of duplicate tags (lattermost tag which
89 * appears is used; tilesets which have duplicates should specify
90 * "duplicates_ok")
93 #define SPEC_CAPSTR "+Freeciv-2.5-spec"
95 * Individual spec file capabilities acceptable to this program:
97 * +Freeciv-2.3-spec
98 * - basic format for Freeciv versions 2.3.x; required
101 #define TILESPEC_SUFFIX ".tilespec"
102 #define TILE_SECTION_PREFIX "tile_"
104 /* This the way directional indices are now encoded: */
105 #define MAX_INDEX_CARDINAL 64
106 #define MAX_INDEX_HALF 16
107 #define MAX_INDEX_VALID 256
109 #define NUM_TILES_HP_BAR 11
110 #define NUM_TILES_DIGITS 10
111 #define NUM_TILES_SELECT 4
112 #define MAX_NUM_CITIZEN_SPRITES 6
113 #define MAX_NUM_UPKEEP_SPRITES 10
115 #define SPECENUM_NAME roadstyle_id
116 #define SPECENUM_VALUE0 RSTYLE_ALL_SEPARATE
117 #define SPECENUM_VALUE0NAME "AllSeparate"
118 #define SPECENUM_VALUE1 RSTYLE_PARITY_COMBINED
119 #define SPECENUM_VALUE1NAME "ParityCombined"
120 #define SPECENUM_VALUE2 RSTYLE_ALL_COMBINED
121 #define SPECENUM_VALUE2NAME "AllCombined"
122 #define SPECENUM_VALUE3 RSTYLE_RIVER
123 #define SPECENUM_VALUE3NAME "River"
124 #include "specenum_gen.h"
126 /* This could be moved to common/map.h if there's more use for it. */
127 enum direction4 {
128 DIR4_NORTH = 0, DIR4_SOUTH, DIR4_EAST, DIR4_WEST
130 static const char direction4letters[4] = "udrl";
131 /* This must correspond to enum edge_type. */
132 static const char edge_name[EDGE_COUNT][3] = {"ns", "we", "ud", "lr"};
134 static const int DIR4_TO_DIR8[4] =
135 { DIR8_NORTH, DIR8_SOUTH, DIR8_EAST, DIR8_WEST };
137 enum match_style {
138 MATCH_NONE,
139 MATCH_SAME, /* "boolean" match */
140 MATCH_PAIR,
141 MATCH_FULL
144 enum sprite_type {
145 CELL_WHOLE, /* entire tile */
146 CELL_CORNER /* corner of tile */
149 struct drawing_data {
150 char *name;
151 char *mine_tag;
153 int num_layers; /* 1 thru MAX_NUM_LAYERS. */
154 #define MAX_NUM_LAYERS 3
156 struct drawing_layer {
157 bool is_tall;
158 int offset_x, offset_y;
160 #define MAX_NUM_MATCH_WITH 8
161 enum match_style match_style;
162 int match_index[1 + MAX_NUM_MATCH_WITH];
163 int match_indices; /* 0 = no match_type, 1 = no match_with */
165 enum sprite_type sprite_type;
167 struct sprite_vector base;
168 struct sprite *match[MAX_INDEX_CARDINAL];
169 struct sprite **cells;
171 /* List of those sprites in 'cells' that are allocated by some other
172 * means than load_sprite() and thus are not freed by unload_all_sprites(). */
173 struct sprite_vector allocated;
174 } layer[MAX_NUM_LAYERS];
176 bool is_reversed;
178 int blending; /* layer, 0 = none */
179 struct sprite *blender;
180 struct sprite *blend[4]; /* indexed by a direction4 */
182 struct sprite *mine;
185 struct city_style_threshold {
186 struct sprite *sprite;
189 struct city_sprite {
190 struct {
191 int land_num_thresholds;
192 struct city_style_threshold *land_thresholds;
193 int oceanic_num_thresholds;
194 struct city_style_threshold *oceanic_thresholds;
195 } *styles;
196 int num_styles;
199 struct river_sprites {
200 struct sprite
201 *spec[MAX_INDEX_CARDINAL],
202 *outlet[4]; /* indexed by enum direction4 */
205 struct named_sprites {
206 struct sprite
207 *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
208 *treaty_thumb[2], /* 0=disagree, 1=agree */
209 *arrow[ARROW_LAST], /* 0=right arrow, 1=plus, 2=minus */
211 *icon[ICON_COUNT],
213 /* The panel sprites for showing tax % allocations. */
214 *tax_luxury, *tax_science, *tax_gold,
215 *dither_tile; /* only used for isometric view */
217 struct {
218 struct sprite
219 *tile,
220 *worked_tile,
221 *unworked_tile;
222 } mask;
224 struct sprite *tech[A_LAST];
225 struct sprite *building[B_LAST];
226 struct sprite *government[G_MAGIC];
228 struct {
229 struct sprite *icon[U_LAST];
230 struct sprite *facing[U_LAST][DIR8_MAGIC_MAX];
231 } units;
233 struct sprite *resource[MAX_NUM_RESOURCES];
235 struct sprite_vector nation_flag;
236 struct sprite_vector nation_shield;
238 struct citizen_graphic {
239 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
240 * sprites, as defined by the tileset. */
241 int count;
242 struct sprite *sprite[MAX_NUM_CITIZEN_SPRITES];
243 } citizen[CITIZEN_LAST], specialist[SP_MAX];
244 struct sprite *spaceship[SPACESHIP_COUNT];
245 struct {
246 int hot_x, hot_y;
247 struct sprite *frame[NUM_CURSOR_FRAMES];
248 } cursor[CURSOR_LAST];
249 struct {
250 enum roadstyle_id roadstyle;
251 struct sprite
252 *activity,
253 /* for roadstyles RSTYLE_ALL_SEPARATE and RSTYLE_PARITY_COMBINED */
254 *isolated,
255 *corner[8]; /* Indexed by direction; only non-cardinal dirs used. */
256 union {
257 /* for RSTYLE_ALL_SEPARATE */
258 struct sprite *dir[8]; /* all entries used */
259 /* RSTYLE_PARITY_COMBINED */
260 struct {
261 struct sprite
262 *even[MAX_INDEX_HALF], /* first unused */
263 *odd[MAX_INDEX_HALF]; /* first unused */
264 } combo;
265 /* RSTYLE_ALL_SEPARATE */
266 struct sprite *total[MAX_INDEX_VALID];
267 struct river_sprites rivers;
268 } u;
269 } roads[MAX_ROAD_TYPES];
270 struct {
271 struct sprite_vector unit;
272 struct sprite *nuke;
273 } explode;
274 struct {
275 struct sprite
276 *hp_bar[NUM_TILES_HP_BAR],
277 *vet_lev[MAX_VET_LEVELS],
278 *select[NUM_TILES_SELECT],
279 *auto_attack,
280 *auto_settler,
281 *auto_explore,
282 *fallout,
283 *fortified,
284 *fortifying,
285 *go_to, /* goto is a C keyword :-) */
286 *irrigate,
287 *mine,
288 *pillage,
289 *pollution,
290 *sentry,
291 *stack,
292 *loaded,
293 *transform,
294 *connect,
295 *patrol,
296 *convert,
297 *battlegroup[MAX_NUM_BATTLEGROUPS],
298 *lowfuel,
299 *tired;
300 } unit;
301 struct {
302 struct sprite
303 *unhappy[MAX_NUM_UPKEEP_SPRITES],
304 *output[O_LAST][MAX_NUM_UPKEEP_SPRITES];
305 } upkeep;
306 struct {
307 struct sprite
308 *disorder,
309 *size[NUM_TILES_DIGITS],
310 *size_tens[NUM_TILES_DIGITS],
311 *size_hundreds[NUM_TILES_DIGITS],
312 *tile_foodnum[NUM_TILES_DIGITS],
313 *tile_shieldnum[NUM_TILES_DIGITS],
314 *tile_tradenum[NUM_TILES_DIGITS];
315 struct city_sprite
316 *tile,
317 *wall,
318 *occupied;
319 struct sprite_vector worked_tile_overlay;
320 struct sprite_vector unworked_tile_overlay;
321 } city;
322 struct citybar_sprites citybar;
323 struct editor_sprites editor;
324 struct {
325 struct sprite
326 *turns[NUM_TILES_DIGITS],
327 *turns_tens[NUM_TILES_DIGITS],
328 *turns_hundreds[NUM_TILES_DIGITS];
329 } path;
330 struct {
331 struct sprite *attention;
332 } user;
333 struct {
334 struct sprite
335 *farmland[MAX_INDEX_CARDINAL],
336 *irrigation[MAX_INDEX_CARDINAL],
337 *pollution,
338 *village,
339 *fallout,
340 *fog,
341 **fullfog,
342 *darkness[MAX_INDEX_CARDINAL]; /* first unused */
343 } tx; /* terrain extra */
344 struct {
345 struct sprite
346 *background,
347 *middleground,
348 *foreground,
349 *activity;
350 } bases[MAX_BASE_TYPES];
351 struct {
352 struct sprite
353 *main[EDGE_COUNT],
354 *city[EDGE_COUNT],
355 *worked[EDGE_COUNT],
356 *unavailable,
357 *nonnative,
358 *selected[EDGE_COUNT],
359 *coastline[EDGE_COUNT],
360 *borders[EDGE_COUNT][2];
361 } grid;
362 struct {
363 struct sprite_vector overlays;
364 } colors;
365 struct {
366 struct sprite *color; /* Generic background color */
367 struct sprite *graphic; /* Generic background graphic */
368 } background;
369 struct {
370 struct sprite *grid_borders[EDGE_COUNT][2];
371 struct sprite *color;
372 struct sprite *background;
373 } player[MAX_NUM_PLAYER_SLOTS];
375 struct drawing_data *drawing[MAX_NUM_ITEMS];
378 /* Don't reorder this enum since tilesets depend on it. */
379 enum fog_style {
380 FOG_AUTO, /* Fog is automatically appended by the code. */
381 FOG_SPRITE, /* A single fog sprite is provided by the tileset (tx.fog). */
382 FOG_NONE /* No fog. */
385 /* Darkness style. Don't reorder this enum since tilesets depend on it. */
386 enum darkness_style {
387 /* No darkness sprites are drawn. */
388 DARKNESS_NONE = 0,
390 /* 1 sprite that is split into 4 parts and treated as a darkness4. Only
391 * works in iso-view. */
392 DARKNESS_ISORECT = 1,
394 /* 4 sprites, one per direction. More than one sprite per tile may be
395 * drawn. */
396 DARKNESS_CARD_SINGLE = 2,
398 /* 15=2^4-1 sprites. A single sprite is drawn, chosen based on whether
399 * there's darkness in _each_ of the cardinal directions. */
400 DARKNESS_CARD_FULL = 3,
402 /* Corner darkness & fog. 3^4 = 81 sprites. */
403 DARKNESS_CORNER = 4
406 struct specfile {
407 struct sprite *big_sprite;
408 char *file_name;
411 #define SPECLIST_TAG specfile
412 #define SPECLIST_TYPE struct specfile
413 #include "speclist.h"
415 #define specfile_list_iterate(list, pitem) \
416 TYPED_LIST_ITERATE(struct specfile, list, pitem)
417 #define specfile_list_iterate_end LIST_ITERATE_END
420 * Information about an individual sprite. All fields except 'sprite' are
421 * filled at the time of the scan of the specfile. 'Sprite' is
422 * set/cleared on demand in load_sprite/unload_sprite.
424 struct small_sprite {
425 int ref_count;
427 /* The sprite is in this file. */
428 char *file;
430 /* Or, the sprite is in this file at the location. */
431 struct specfile *sf;
432 int x, y, width, height;
434 /* A little more (optional) data. */
435 int hot_x, hot_y;
437 struct sprite *sprite;
440 /* 'struct small_sprite_list' and related functions. */
441 #define SPECLIST_TAG small_sprite
442 #define SPECLIST_TYPE struct small_sprite
443 #include "speclist.h"
444 #define small_sprite_list_iterate(list, pitem) \
445 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
446 #define small_sprite_list_iterate_end LIST_ITERATE_END
448 /* 'struct sprite_hash' and related functions. */
449 #define SPECHASH_TAG sprite
450 #define SPECHASH_KEY_TYPE char *
451 #define SPECHASH_DATA_TYPE struct small_sprite *
452 #define SPECHASH_KEY_VAL genhash_str_val_func
453 #define SPECHASH_KEY_COMP genhash_str_comp_func
454 #define SPECHASH_KEY_COPY genhash_str_copy_func
455 #define SPECHASH_KEY_FREE genhash_str_free_func
456 #include "spechash.h"
457 #define sprite_hash_iterate(hash, tag_name, sprite) \
458 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
459 hash, tag_name, sprite)
460 #define sprite_hash_iterate_end HASH_ITERATE_END
462 /* 'struct drawing_hash' and related functions. */
463 static void drawing_data_destroy(struct drawing_data *draw);
465 #define SPECHASH_TAG drawing
466 #define SPECHASH_KEY_TYPE char *
467 #define SPECHASH_DATA_TYPE struct drawing_data *
468 #define SPECHASH_KEY_VAL genhash_str_val_func
469 #define SPECHASH_KEY_COMP genhash_str_comp_func
470 #define SPECHASH_DATA_FREE drawing_data_destroy
471 #include "spechash.h"
473 #define SPECHASH_TAG rstyle
474 #define SPECHASH_KEY_TYPE char *
475 #define SPECHASH_DATA_TYPE enum roadstyle_id *
476 #define SPECHASH_KEY_VAL genhash_str_val_func
477 #define SPECHASH_KEY_COMP genhash_str_comp_func
478 #include "spechash.h"
480 enum ts_type { TS_OVERVIEW, TS_ISOMETRIC };
482 struct tileset {
483 char name[512];
484 int priority;
486 enum ts_type type;
487 int hex_width, hex_height;
489 int normal_tile_width, normal_tile_height;
490 int full_tile_width, full_tile_height;
491 int unit_tile_width, unit_tile_height;
492 int small_sprite_width, small_sprite_height;
494 char *main_intro_filename;
495 char *minimap_intro_filename;
497 int city_names_font_size, city_productions_font_size;
499 enum fog_style fogstyle;
500 enum darkness_style darkness_style;
501 int darkness_layer;
503 int unit_flag_offset_x, unit_flag_offset_y;
504 int city_flag_offset_x, city_flag_offset_y;
505 int unit_offset_x, unit_offset_y;
507 int citybar_offset_y;
508 int tilelabel_offset_y;
510 #define NUM_CORNER_DIRS 4
511 #define TILES_PER_CORNER 4
512 int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
513 int num_index_valid, num_index_cardinal;
514 enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
516 struct tileset_layer {
517 char **match_types;
518 size_t match_count;
519 } layers[MAX_NUM_LAYERS];
521 struct specfile_list *specfiles;
522 struct small_sprite_list *small_sprites;
524 /* This hash table maps tilespec tags to struct small_sprites. */
525 struct sprite_hash *sprite_hash;
527 /* This hash table maps terrain graphic strings to drawing data. */
528 struct drawing_hash *tile_hash;
530 struct rstyle_hash *rstyle_hash;
532 struct named_sprites sprites;
534 struct color_system *color_system;
536 struct road_type_list *rivers;
538 int num_prefered_themes;
539 char** prefered_themes;
542 struct tileset *tileset;
544 int focus_unit_state = 0;
547 static int fill_unit_type_sprite_array(const struct tileset *t,
548 struct drawn_sprite *sprs,
549 const struct unit_type *putype,
550 enum direction8 facing);
551 static int fill_unit_sprite_array(const struct tileset *t,
552 struct drawn_sprite *sprs,
553 const struct unit *punit,
554 bool stack, bool backdrop);
555 static bool load_river_sprites(struct tileset *t,
556 struct river_sprites *store, const char *tag_pfx);
558 /****************************************************************************
559 Called when ever there's problem in ruleset/tileset compatibility
560 ****************************************************************************/
561 static void tileset_error(enum log_level level, const char *format, ...)
563 char buf[2048];
564 va_list args;
566 va_start(args, format);
567 fc_vsnprintf(buf, sizeof(buf), format, args);
568 va_end(args);
570 show_tileset_error(buf);
572 if (level == LOG_FATAL) {
573 exit(EXIT_FAILURE);
577 /****************************************************************************
578 Create a new drawing data.
579 ****************************************************************************/
580 static struct drawing_data *drawing_data_new(const char *name)
582 struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
584 draw->name = fc_strdup(name);
585 return draw;
588 /****************************************************************************
589 Free a drawing data.
590 ****************************************************************************/
591 static void drawing_data_destroy(struct drawing_data *draw)
593 int i;
595 fc_assert_ret(NULL != draw);
597 free(draw->name);
598 if (NULL != draw->mine_tag) {
599 free(draw->mine_tag);
601 for (i = 0; i < 4; i++) {
602 if (draw->blend[i]) {
603 free_sprite(draw->blend[i]);
606 for (i = 0; i < draw->num_layers; i++) {
607 int vec_size = sprite_vector_size(&draw->layer[i].allocated);
608 int j;
610 for (j = 0; j < vec_size; j++) {
611 free_sprite(draw->layer[i].allocated.p[j]);
614 sprite_vector_free(&draw->layer[i].base);
615 sprite_vector_free(&draw->layer[i].allocated);
617 free(draw);
620 /****************************************************************************
621 Return the name of the given tileset.
622 ****************************************************************************/
623 const char *tileset_get_name(const struct tileset *t)
625 return t->name;
628 /****************************************************************************
629 Return whether the current tileset is isometric.
630 ****************************************************************************/
631 bool tileset_is_isometric(const struct tileset *t)
633 return t->type == TS_ISOMETRIC;
636 /****************************************************************************
637 Return the hex_width of the current tileset. For hex tilesets this value
638 will be > 0 and is_isometric will be set.
639 ****************************************************************************/
640 int tileset_hex_width(const struct tileset *t)
642 return t->hex_width;
645 /****************************************************************************
646 Return the hex_height of the current tileset. For iso-hex tilesets this
647 value will be > 0 and is_isometric will be set.
648 ****************************************************************************/
649 int tileset_hex_height(const struct tileset *t)
651 return t->hex_height;
654 /****************************************************************************
655 Return the tile width of the current tileset. This is the tesselation
656 width of the tiled plane. This means it's the width of the bounding box
657 of the basic map tile.
659 For best results:
660 - The value should be even (or a multiple of 4 in iso-view).
661 - In iso-view, the width should be twice the height (to give a
662 perspective of 30 degrees above the horizon).
663 - In non-iso-view, width and height should be equal (overhead
664 perspective).
665 - In hex or iso-hex view, remember this is the tesselation vector.
666 hex_width and hex_height then give the size of the side of the
667 hexagon. Calculating the dimensions of a "regular" hexagon or
668 iso-hexagon may be tricky.
669 However these requirements are not absolute and callers should not
670 depend on them (although some do).
671 ****************************************************************************/
672 int tileset_tile_width(const struct tileset *t)
674 return t->normal_tile_width;
677 /****************************************************************************
678 Return the tile height of the current tileset. This is the tesselation
679 height of the tiled plane. This means it's the height of the bounding box
680 of the basic map tile.
682 See also tileset_tile_width.
683 ****************************************************************************/
684 int tileset_tile_height(const struct tileset *t)
686 return t->normal_tile_height;
689 /****************************************************************************
690 Return the full tile width of the current tileset. This is the maximum
691 width that any mapview sprite will have.
693 Note: currently this is always equal to the tile width.
694 ****************************************************************************/
695 int tileset_full_tile_width(const struct tileset *t)
697 return t->full_tile_width;
700 /****************************************************************************
701 Return the full tile height of the current tileset. This is the maximum
702 height that any mapview sprite will have. This may be greater than the
703 tile width in which case the extra area is above the "normal" tile.
705 Some callers assume the full height is 50% larger than the height in
706 iso-view, and equal in non-iso view.
707 ****************************************************************************/
708 int tileset_full_tile_height(const struct tileset *t)
710 return t->full_tile_height;
713 /****************************************************************************
714 Return the unit tile width of the current tileset.
715 ****************************************************************************/
716 int tileset_unit_width(const struct tileset *t)
718 return t->unit_tile_width;
721 /****************************************************************************
722 Return the unit tile height of the current tileset.
723 ****************************************************************************/
724 int tileset_unit_height(const struct tileset *t)
726 return t->unit_tile_height;
729 /****************************************************************************
730 Return the small sprite width of the current tileset. The small sprites
731 are used for various theme graphics (e.g., citymap citizens/specialists
732 as well as panel indicator icons).
733 ****************************************************************************/
734 int tileset_small_sprite_width(const struct tileset *t)
736 return t->small_sprite_width;
739 /****************************************************************************
740 Return the offset from the origin of the city tile at which to place the
741 city bar text.
742 ****************************************************************************/
743 int tileset_citybar_offset_y(const struct tileset *t)
745 return t->citybar_offset_y;
748 /****************************************************************************
749 Return the offset from the origin of the tile at which to place the
750 label text.
751 ****************************************************************************/
752 int tileset_tilelabel_offset_y(const struct tileset *t)
754 return t->tilelabel_offset_y;
757 /****************************************************************************
758 Return the small sprite height of the current tileset. The small sprites
759 are used for various theme graphics (e.g., citymap citizens/specialists
760 as well as panel indicator icons).
761 ****************************************************************************/
762 int tileset_small_sprite_height(const struct tileset *t)
764 return t->small_sprite_height;
767 /****************************************************************************
768 Return the path within the data directories where the main intro graphics
769 file can be found. (It is left up to the GUI code to load and unload this
770 file.)
771 ****************************************************************************/
772 const char *tileset_main_intro_filename(const struct tileset *t)
774 return t->main_intro_filename;
777 /****************************************************************************
778 Return the path within the data directories where the mini intro graphics
779 file can be found. (It is left up to the GUI code to load and unload this
780 file.)
781 ****************************************************************************/
782 const char *tileset_mini_intro_filename(const struct tileset *t)
784 return t->minimap_intro_filename;
787 /****************************************************************************
788 Return the number of possible colors for city overlays.
789 ****************************************************************************/
790 int tileset_num_city_colors(const struct tileset *t)
792 return t->sprites.city.worked_tile_overlay.size;
795 /****************************************************************************
796 Return TRUE if the client will use the code to generate the fog.
797 ****************************************************************************/
798 bool tileset_use_hard_coded_fog(const struct tileset *t)
800 return FOG_AUTO == t->fogstyle;
803 /**************************************************************************
804 Initialize.
805 **************************************************************************/
806 static struct tileset *tileset_new(void)
808 struct tileset *t = fc_calloc(1, sizeof(*t));
810 t->specfiles = specfile_list_new();
811 t->small_sprites = small_sprite_list_new();
812 return t;
815 /**************************************************************************
816 Return the tileset name of the direction. This is similar to
817 dir_get_name but you shouldn't change this or all tilesets will break.
818 **************************************************************************/
819 static const char *dir_get_tileset_name(enum direction8 dir)
821 switch (dir) {
822 case DIR8_NORTH:
823 return "n";
824 case DIR8_NORTHEAST:
825 return "ne";
826 case DIR8_EAST:
827 return "e";
828 case DIR8_SOUTHEAST:
829 return "se";
830 case DIR8_SOUTH:
831 return "s";
832 case DIR8_SOUTHWEST:
833 return "sw";
834 case DIR8_WEST:
835 return "w";
836 case DIR8_NORTHWEST:
837 return "nw";
839 log_error("Wrong direction8 variant: %d.", dir);
840 return "";
843 /****************************************************************************
844 Return TRUE iff the dir is valid in this tileset.
845 ****************************************************************************/
846 static bool is_valid_tileset_dir(const struct tileset *t,
847 enum direction8 dir)
849 if (t->hex_width > 0) {
850 return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
851 } else if (t->hex_height > 0) {
852 return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
853 } else {
854 return TRUE;
858 /****************************************************************************
859 Return TRUE iff the dir is cardinal in this tileset.
861 "Cardinal", in this sense, means that a tile will share a border with
862 another tile in the direction rather than sharing just a single vertex.
863 ****************************************************************************/
864 static bool is_cardinal_tileset_dir(const struct tileset *t,
865 enum direction8 dir)
867 if (t->hex_width > 0 || t->hex_height > 0) {
868 return is_valid_tileset_dir(t, dir);
869 } else {
870 return (dir == DIR8_NORTH || dir == DIR8_EAST
871 || dir == DIR8_SOUTH || dir == DIR8_WEST);
875 /**********************************************************************
876 Returns a static list of tilesets available on the system by
877 searching all data directories for files matching TILESPEC_SUFFIX.
878 ***********************************************************************/
879 const struct strvec *get_tileset_list(void)
881 static struct strvec *tilesets = NULL;
883 if (!tilesets) {
884 /* Note: this means you must restart the client after installing a new
885 tileset. */
886 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
888 tilesets = strvec_new();
889 strvec_iterate(list, file) {
890 struct tileset *t = tileset_read_toplevel(file, FALSE);
892 if (t) {
893 strvec_append(tilesets, file);
894 tileset_free(t);
896 } strvec_iterate_end;
897 strvec_destroy(list);
900 return tilesets;
903 /**********************************************************************
904 Gets full filename for tilespec file, based on input name.
905 Returned data is allocated, and freed by user as required.
906 Input name may be null, in which case uses default.
907 Falls back to default if can't find specified name;
908 dies if can't find default.
909 ***********************************************************************/
910 static char *tilespec_fullname(const char *tileset_name)
912 if (tileset_name) {
913 char fname[strlen(tileset_name) + strlen(TILESPEC_SUFFIX) + 1];
914 const char *dname;
916 fc_snprintf(fname, sizeof(fname),
917 "%s%s", tileset_name, TILESPEC_SUFFIX);
919 dname = fileinfoname(get_data_dirs(), fname);
921 if (dname) {
922 return fc_strdup(dname);
926 return NULL;
929 /**********************************************************************
930 Checks options in filename match what we require and support.
931 Die if not.
932 'which' should be "tilespec" or "spec".
933 ***********************************************************************/
934 static bool check_tilespec_capabilities(struct section_file *file,
935 const char *which,
936 const char *us_capstr,
937 const char *filename,
938 bool verbose)
940 enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
942 const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
944 if (NULL == file_capstr) {
945 log_base(level, "\"%s\": %s file doesn't have a capability string",
946 filename, which);
947 return FALSE;
949 if (!has_capabilities(us_capstr, file_capstr)) {
950 log_base(level, "\"%s\": %s file appears incompatible:",
951 filename, which);
952 log_base(level, " datafile options: %s", file_capstr);
953 log_base(level, " supported options: %s", us_capstr);
954 return FALSE;
956 if (!has_capabilities(file_capstr, us_capstr)) {
957 log_base(level, "\"%s\": %s file requires option(s) "
958 "that client doesn't support:", filename, which);
959 log_base(level, " datafile options: %s", file_capstr);
960 log_base(level, " supported options: %s", us_capstr);
961 return FALSE;
964 return TRUE;
967 /**********************************************************************
968 Frees the tilespec toplevel data, in preparation for re-reading it.
970 See tilespec_read_toplevel().
971 ***********************************************************************/
972 static void tileset_free_toplevel(struct tileset *t)
974 int i, j;
976 if (t->main_intro_filename) {
977 free(t->main_intro_filename);
978 t->main_intro_filename = NULL;
980 if (t->minimap_intro_filename) {
981 free(t->minimap_intro_filename);
982 t->minimap_intro_filename = NULL;
985 if (t->prefered_themes) {
986 for (i = 0; i < t->num_prefered_themes; i++) {
987 free(t->prefered_themes[i]);
989 free(t->prefered_themes);
990 t->prefered_themes = NULL;
992 t->num_prefered_themes = 0;
994 if (t->tile_hash) {
995 drawing_hash_destroy(t->tile_hash);
996 t->tile_hash = NULL; /* Helpful for sanity. */
998 if (t->rstyle_hash) {
999 rstyle_hash_destroy(t->rstyle_hash);
1000 t->rstyle_hash = NULL;
1002 if (t->rivers != NULL) {
1003 road_type_list_destroy(t->rivers);
1004 t->rivers = NULL;
1007 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1008 struct tileset_layer *tslp = &t->layers[i];
1010 if (tslp->match_types) {
1011 for (j = 0; j < tslp->match_count; j++) {
1012 free(tslp->match_types[j]);
1014 free(tslp->match_types);
1015 tslp->match_types = NULL;
1019 if (t->color_system) {
1020 color_system_free(t->color_system);
1021 t->color_system = NULL;
1025 /**************************************************************************
1026 Clean up.
1027 **************************************************************************/
1028 void tileset_free(struct tileset *t)
1030 tileset_free_tiles(t);
1031 tileset_free_toplevel(t);
1032 players_iterate(pplayer) {
1033 tileset_player_free(t, pplayer);
1034 } players_iterate_end;
1035 specfile_list_destroy(t->specfiles);
1036 small_sprite_list_destroy(t->small_sprites);
1037 free(t);
1040 /**********************************************************************
1041 Read a new tilespec in when first starting the game.
1043 Call this function with the (guessed) name of the tileset, when
1044 starting the client.
1045 ***********************************************************************/
1046 void tilespec_try_read(const char *tileset_name, bool verbose)
1048 if (!(tileset = tileset_read_toplevel(tileset_name, verbose))) {
1049 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1051 strvec_iterate(list, file) {
1052 struct tileset *t = tileset_read_toplevel(file, FALSE);
1054 if (t) {
1055 if (!tileset) {
1056 tileset = t;
1057 } else if (t->priority > tileset->priority) {
1058 tileset_free(tileset);
1059 tileset = t;
1060 } else {
1061 tileset_free(t);
1064 } strvec_iterate_end;
1065 strvec_destroy(list);
1067 if (!tileset) {
1068 tileset_error(LOG_FATAL, _("No usable default tileset found, aborting!"));
1071 log_verbose("Trying tileset \"%s\".", tileset->name);
1073 sz_strlcpy(default_tileset_name, tileset_get_name(tileset));
1076 /**********************************************************************
1077 Read a new tilespec in from scratch.
1079 Unlike the initial reading code, which reads pieces one at a time,
1080 this gets rid of the old data and reads in the new all at once. If the
1081 new tileset fails to load the old tileset may be reloaded; otherwise the
1082 client will exit. If a NULL name is given the current tileset will be
1083 reread.
1085 It will also call the necessary functions to redraw the graphics.
1086 ***********************************************************************/
1087 void tilespec_reread(const char *new_tileset_name, bool game_fully_initialized)
1089 int id;
1090 struct tile *center_tile;
1091 enum client_states state = client_state();
1092 const char *name = new_tileset_name ? new_tileset_name : tileset->name;
1093 char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1095 /* Make local copies since these values may be freed down below */
1096 sz_strlcpy(tileset_name, name);
1097 sz_strlcpy(old_name, tileset->name);
1099 log_normal(_("Loading tileset \"%s\"."), tileset_name);
1101 /* Step 0: Record old data.
1103 * We record the current mapcanvas center, etc.
1105 center_tile = get_center_tile_mapcanvas();
1107 /* Step 1: Cleanup.
1109 * We free all old data in preparation for re-reading it.
1111 tileset_free_tiles(tileset);
1112 tileset_free_toplevel(tileset);
1113 players_iterate(pplayer) {
1114 tileset_player_free(tileset, pplayer);
1115 } players_iterate_end;
1117 /* Step 2: Read.
1119 * We read in the new tileset. This should be pretty straightforward.
1121 if (!(tileset = tileset_read_toplevel(tileset_name, FALSE))) {
1122 if (!(tileset = tileset_read_toplevel(old_name, FALSE))) {
1123 /* Always fails. */
1124 fc_assert_exit_msg(NULL != tileset,
1125 "Failed to re-read the currently loaded tileset.");
1128 sz_strlcpy(default_tileset_name, tileset->name);
1129 tileset_load_tiles(tileset);
1130 tileset_use_prefered_theme(tileset);
1132 if (game_fully_initialized) {
1133 players_iterate(pplayer) {
1134 tileset_player_init(tileset, pplayer);
1135 } players_iterate_end;
1136 tileset_background_init(tileset);
1139 /* Step 3: Setup
1141 * This is a seriously sticky problem. On startup, we build a hash
1142 * from all the sprite data. Then, when we connect to a server, the
1143 * server sends us ruleset data a piece at a time and we use this data
1144 * to assemble the sprite structures. But if we change while connected
1145 * we have to reassemble all of these. This should just involve
1146 * calling tilespec_setup_*** on everything. But how do we tell what
1147 * "everything" is?
1149 * The below code just does things straightforwardly, by setting up
1150 * each possible sprite again. Hopefully it catches everything, and
1151 * doesn't mess up too badly if we change tilesets while not connected
1152 * to a server.
1154 if (state < C_S_RUNNING) {
1155 /* The ruleset data is not sent until this point. */
1156 return;
1158 terrain_type_iterate(pterrain) {
1159 tileset_setup_tile_type(tileset, pterrain);
1160 } terrain_type_iterate_end;
1161 resource_type_iterate(presource) {
1162 tileset_setup_resource(tileset, presource);
1163 } resource_type_iterate_end;
1164 unit_type_iterate(punittype) {
1165 tileset_setup_unit_type(tileset, punittype);
1166 } unit_type_iterate_end;
1167 governments_iterate(gov) {
1168 tileset_setup_government(tileset, gov);
1169 } governments_iterate_end;
1170 road_type_iterate(proad) {
1171 tileset_setup_road(tileset, proad);
1172 } road_type_iterate_end;
1173 base_type_iterate(pbase) {
1174 tileset_setup_base(tileset, pbase);
1175 } base_type_iterate_end;
1176 nations_iterate(pnation) {
1177 tileset_setup_nation_flag(tileset, pnation);
1178 } nations_iterate_end;
1179 improvement_iterate(pimprove) {
1180 tileset_setup_impr_type(tileset, pimprove);
1181 } improvement_iterate_end;
1182 advance_iterate(A_FIRST, padvance) {
1183 tileset_setup_tech_type(tileset, padvance);
1184 } advance_iterate_end;
1185 specialist_type_iterate(sp) {
1186 tileset_setup_specialist_type(tileset, sp);
1187 } specialist_type_iterate_end;
1189 for (id = 0; id < game.control.styles_count; id++) {
1190 tileset_setup_city_tiles(tileset, id);
1193 /* Step 4: Draw.
1195 * Do any necessary redraws.
1197 generate_citydlg_dimensions();
1198 tileset_changed();
1199 can_slide = FALSE;
1200 center_tile_mapcanvas(center_tile);
1201 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1202 * drawing we might not get one. Of course this is slower. */
1203 update_map_canvas_visible();
1204 can_slide = TRUE;
1207 /**************************************************************************
1208 This is merely a wrapper for tilespec_reread (above) for use in
1209 options.c and the client local options dialog.
1210 **************************************************************************/
1211 void tilespec_reread_callback(struct option *poption)
1213 const char *tileset_name = option_str_get(poption);
1215 fc_assert_ret(NULL != tileset_name && tileset_name[0] != '\0');
1216 tilespec_reread(tileset_name, TRUE);
1217 menus_init();
1220 /**************************************************************************
1221 Loads the given graphics file (found in the data path) into a newly
1222 allocated sprite.
1223 **************************************************************************/
1224 static struct sprite *load_gfx_file(const char *gfx_filename)
1226 const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
1227 struct sprite *s;
1229 /* Try out all supported file extensions to find one that works. */
1230 while ((gfx_fileext = *gfx_fileexts++)) {
1231 const char *real_full_name;
1232 char full_name[strlen(gfx_filename) + strlen(gfx_fileext) + 2];
1234 sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
1235 if ((real_full_name = fileinfoname(get_data_dirs(), full_name))) {
1236 log_debug("trying to load gfx file \"%s\".", real_full_name);
1237 s = load_gfxfile(real_full_name);
1238 if (s) {
1239 return s;
1244 log_error("Could not load gfx file \"%s\".", gfx_filename);
1245 return NULL;
1248 /**************************************************************************
1249 Ensure that the big sprite of the given spec file is loaded.
1250 **************************************************************************/
1251 static void ensure_big_sprite(struct specfile *sf)
1253 struct section_file *file;
1254 const char *gfx_filename;
1256 if (sf->big_sprite) {
1257 /* Looks like it's already loaded. */
1258 return;
1261 /* Otherwise load it. The big sprite will sometimes be freed and will have
1262 * to be reloaded, but most of the time it's just loaded once, the small
1263 * sprites are extracted, and then it's freed. */
1264 if (!(file = secfile_load(sf->file_name, TRUE))) {
1265 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1268 if (!check_tilespec_capabilities(file, "spec",
1269 SPEC_CAPSTR, sf->file_name, TRUE)) {
1270 tileset_error(LOG_FATAL, _("Incompatible tileset capabilities"));
1273 gfx_filename = secfile_lookup_str(file, "file.gfx");
1275 sf->big_sprite = load_gfx_file(gfx_filename);
1277 if (!sf->big_sprite) {
1278 tileset_error(LOG_FATAL, _("Could not load gfx file for the spec file \"%s\"."),
1279 sf->file_name);
1281 secfile_destroy(file);
1284 /**************************************************************************
1285 Scan all sprites declared in the given specfile. This means that the
1286 positions of the sprites in the big_sprite are saved in the
1287 small_sprite structs.
1288 **************************************************************************/
1289 static void scan_specfile(struct tileset *t, struct specfile *sf,
1290 bool duplicates_ok)
1292 struct section_file *file;
1293 struct section_list *sections;
1294 int i;
1296 if (!(file = secfile_load(sf->file_name, TRUE))) {
1297 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1299 if (!check_tilespec_capabilities(file, "spec",
1300 SPEC_CAPSTR, sf->file_name, TRUE)) {
1301 tileset_error(LOG_FATAL, _("Specfile %s has incompatible capabilities"), sf->file_name);
1304 /* currently unused */
1305 (void) secfile_entry_lookup(file, "info.artists");
1307 if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1308 section_list_iterate(sections, psection) {
1309 int j, k;
1310 int x_top_left, y_top_left, dx, dy;
1311 int pixel_border;
1312 const char *sec_name = section_name(psection);
1314 pixel_border = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1315 sec_name);
1317 if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1318 || !secfile_lookup_int(file, &y_top_left,
1319 "%s.y_top_left", sec_name)
1320 || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1321 || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1322 log_error("Grid \"%s\" invalid: %s", sec_name, secfile_error());
1323 continue;
1326 j = -1;
1327 while (NULL != secfile_entry_lookup(file, "%s.tiles%d.tag",
1328 sec_name, ++j)) {
1329 struct small_sprite *ss;
1330 int row, column;
1331 int x1, y1;
1332 const char **tags;
1333 size_t num_tags;
1334 int hot_x, hot_y;
1336 if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1337 || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1338 sec_name, j)
1339 || !(tags = secfile_lookup_str_vec(file, &num_tags,
1340 "%s.tiles%d.tag",
1341 sec_name, j))) {
1342 log_error("Small sprite \"%s.tiles%d\" invalid: %s",
1343 sec_name, j, secfile_error());
1344 continue;
1346 hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1347 sec_name, j);
1348 hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1349 sec_name, j);
1351 /* there must be at least 1 because of the while(): */
1352 fc_assert_action(num_tags > 0, continue);
1354 x1 = x_top_left + (dx + pixel_border) * column;
1355 y1 = y_top_left + (dy + pixel_border) * row;
1357 ss = fc_malloc(sizeof(*ss));
1358 ss->ref_count = 0;
1359 ss->file = NULL;
1360 ss->x = x1;
1361 ss->y = y1;
1362 ss->width = dx;
1363 ss->height = dy;
1364 ss->sf = sf;
1365 ss->sprite = NULL;
1366 ss->hot_x = hot_x;
1367 ss->hot_y = hot_y;
1369 small_sprite_list_prepend(t->small_sprites, ss);
1371 if (!duplicates_ok) {
1372 for (k = 0; k < num_tags; k++) {
1373 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1374 log_error("warning: already have a sprite for \"%s\".",
1375 tags[k]);
1378 } else {
1379 for (k = 0; k < num_tags; k++) {
1380 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1384 free(tags);
1385 tags = NULL;
1387 } section_list_iterate_end;
1388 section_list_destroy(sections);
1391 /* Load "extra" sprites. Each sprite is one file. */
1392 i = -1;
1393 while (NULL != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1394 struct small_sprite *ss;
1395 const char **tags;
1396 const char *filename;
1397 size_t num_tags, k;
1398 int hot_x, hot_y;
1400 if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1401 "extra.sprites%d.tag", i))
1402 || !(filename = secfile_lookup_str(file,
1403 "extra.sprites%d.file", i))) {
1404 log_error("Extra sprite \"extra.sprites%d\" invalid: %s",
1405 i, secfile_error());
1406 continue;
1408 hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1409 hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1411 ss = fc_malloc(sizeof(*ss));
1412 ss->ref_count = 0;
1413 ss->file = fc_strdup(filename);
1414 ss->sf = NULL;
1415 ss->sprite = NULL;
1416 ss->hot_x = hot_x;
1417 ss->hot_y = hot_y;
1419 small_sprite_list_prepend(t->small_sprites, ss);
1421 if (!duplicates_ok) {
1422 for (k = 0; k < num_tags; k++) {
1423 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1424 log_error("warning: already have a sprite for \"%s\".", tags[k]);
1427 } else {
1428 for (k = 0; k < num_tags; k++) {
1429 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1432 free(tags);
1435 secfile_check_unused(file);
1436 secfile_destroy(file);
1439 /**********************************************************************
1440 Returns the correct name of the gfx file (with path and extension)
1441 Must be free'd when no longer used
1442 ***********************************************************************/
1443 static char *tilespec_gfx_filename(const char *gfx_filename)
1445 const char *gfx_current_fileext;
1446 const char **gfx_fileexts = gfx_fileextensions();
1448 while((gfx_current_fileext = *gfx_fileexts++))
1450 char *full_name =
1451 fc_malloc(strlen(gfx_filename) + strlen(gfx_current_fileext) + 2);
1452 const char *real_full_name;
1454 sprintf(full_name,"%s.%s",gfx_filename,gfx_current_fileext);
1456 real_full_name = fileinfoname(get_data_dirs(), full_name);
1457 free(full_name);
1458 if (real_full_name) {
1459 return fc_strdup(real_full_name);
1463 tileset_error(LOG_FATAL, _("Couldn't find a supported gfx file extension for \"%s\"."),
1464 gfx_filename);
1466 return NULL;
1469 /**********************************************************************
1470 Determine the sprite_type string.
1471 ***********************************************************************/
1472 static int check_sprite_type(const char *sprite_type, const char *tile_section)
1474 if (fc_strcasecmp(sprite_type, "corner") == 0) {
1475 return CELL_CORNER;
1477 if (fc_strcasecmp(sprite_type, "single") == 0) {
1478 return CELL_WHOLE;
1480 if (fc_strcasecmp(sprite_type, "whole") == 0) {
1481 return CELL_WHOLE;
1483 log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1484 return CELL_WHOLE;
1487 /**********************************************************************
1488 Finds and reads the toplevel tilespec file based on given name.
1489 Sets global variables, including tile sizes and full names for
1490 intro files.
1491 ***********************************************************************/
1492 struct tileset *tileset_read_toplevel(const char *tileset_name, bool verbose)
1494 struct section_file *file;
1495 char *fname;
1496 const char *c;
1497 int i;
1498 size_t num_spec_files;
1499 const char **spec_filenames;
1500 size_t num_prefered_themes;
1501 struct section_list *sections = NULL;
1502 const char *file_capstr;
1503 bool duplicates_ok, is_hex;
1504 enum direction8 dir;
1505 const int spl = strlen(TILE_SECTION_PREFIX);
1506 struct tileset *t = NULL;
1507 int ei1, ei2;
1508 const char *roadname;
1509 const char *tstr;
1511 fname = tilespec_fullname(tileset_name);
1512 if (!fname) {
1513 if (verbose) {
1514 log_error("Can't find tileset \"%s\".", tileset_name);
1516 return NULL;
1518 log_verbose("tilespec file is \"%s\".", fname);
1520 if (!(file = secfile_load(fname, TRUE))) {
1521 log_error("Could not open '%s':\n%s", fname, secfile_error());
1522 free(fname);
1523 return NULL;
1526 if (!check_tilespec_capabilities(file, "tilespec",
1527 TILESPEC_CAPSTR, fname, verbose)) {
1528 secfile_destroy(file);
1529 free(fname);
1530 return NULL;
1533 t = tileset_new();
1534 file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1535 duplicates_ok = (NULL != file_capstr
1536 && has_capabilities("+duplicates_ok", file_capstr));
1538 (void) secfile_entry_lookup(file, "tilespec.name"); /* currently unused */
1540 sz_strlcpy(t->name, tileset_name);
1541 if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1542 || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1543 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1544 goto ON_ERROR;
1547 tstr = secfile_lookup_str(file, "tilespec.type");
1548 if (tstr == NULL) {
1549 log_error("Tileset \"%s\": no tileset type", t->name);
1550 goto ON_ERROR;
1553 if (!fc_strcasecmp(tstr, "overview")) {
1554 t->type = TS_OVERVIEW;
1555 } else if (!fc_strcasecmp(tstr, "isometric")) {
1556 t->type = TS_ISOMETRIC;
1557 } else {
1558 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1559 goto ON_ERROR;
1562 /* Read hex-tileset information. */
1563 t->hex_width = t->hex_height = 0;
1564 if (is_hex) {
1565 int hex_side;
1567 if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1568 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1569 goto ON_ERROR;
1572 if (t->type == TS_ISOMETRIC) {
1573 t->hex_width = hex_side;
1574 } else {
1575 t->hex_height = hex_side;
1577 /* Hex tilesets are drawn the same as isometric. */
1578 /* FIXME: There will be other legal values to be used with hex
1579 * tileset in the future, and this would just overwrite it. */
1580 t->type = TS_ISOMETRIC;
1583 if (t->type == TS_ISOMETRIC && !isometric_view_supported()) {
1584 log_normal(_("Client does not support isometric tilesets."));
1585 log_normal(_("Using default tileset instead."));
1586 fc_assert(tileset_name != NULL);
1587 goto ON_ERROR;
1589 if (t->type == TS_OVERVIEW && !overhead_view_supported()) {
1590 log_normal(_("Client does not support overhead view tilesets."));
1591 log_normal(_("Using default tileset instead."));
1592 fc_assert(tileset_name != NULL);
1593 goto ON_ERROR;
1596 /* Create arrays of valid and cardinal tileset dirs. These depend
1597 * entirely on the tileset, not the topology. They are also in clockwise
1598 * rotational ordering. */
1599 t->num_valid_tileset_dirs = t->num_cardinal_tileset_dirs = 0;
1600 dir = DIR8_NORTH;
1601 do {
1602 if (is_valid_tileset_dir(t, dir)) {
1603 t->valid_tileset_dirs[t->num_valid_tileset_dirs] = dir;
1604 t->num_valid_tileset_dirs++;
1606 if (is_cardinal_tileset_dir(t, dir)) {
1607 t->cardinal_tileset_dirs[t->num_cardinal_tileset_dirs] = dir;
1608 t->num_cardinal_tileset_dirs++;
1611 dir = dir_cw(dir);
1612 } while (dir != DIR8_NORTH);
1613 fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
1614 t->num_index_valid = 1 << t->num_valid_tileset_dirs;
1615 t->num_index_cardinal = 1 << t->num_cardinal_tileset_dirs;
1617 if (!secfile_lookup_int(file, &t->normal_tile_width,
1618 "tilespec.normal_tile_width")
1619 || !secfile_lookup_int(file, &t->normal_tile_height,
1620 "tilespec.normal_tile_height")) {
1621 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1622 goto ON_ERROR;
1624 if (t->type == TS_ISOMETRIC) {
1625 t->full_tile_width = t->normal_tile_width;
1626 if (tileset_hex_height(t) > 0) {
1627 t->full_tile_height = t->normal_tile_height;
1628 } else {
1629 t->full_tile_height = 3 * t->normal_tile_height / 2;
1631 } else {
1632 t->full_tile_width = t->normal_tile_width;
1633 t->full_tile_height = t->normal_tile_height;
1635 t->unit_tile_width
1636 = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
1637 t->unit_tile_height
1638 = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
1639 if (!secfile_lookup_int(file, &t->small_sprite_width,
1640 "tilespec.small_tile_width")
1641 || !secfile_lookup_int(file, &t->small_sprite_height,
1642 "tilespec.small_tile_height")) {
1643 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1644 goto ON_ERROR;
1646 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1647 t->normal_tile_width, t->normal_tile_height,
1648 t->full_tile_width, t->full_tile_height,
1649 t->small_sprite_width, t->small_sprite_height);
1651 /* FIXME: use specenum to load these. */
1652 if (!secfile_lookup_int(file, &ei1,
1653 "tilespec.fogstyle")
1654 || !secfile_lookup_int(file, &ei2,
1655 "tilespec.darkness_style")) {
1656 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1657 goto ON_ERROR;
1659 t->fogstyle = ei1;
1660 t->darkness_style = ei2;
1662 if (t->darkness_style < DARKNESS_NONE
1663 || t->darkness_style > DARKNESS_CORNER
1664 || (t->darkness_style == DARKNESS_ISORECT
1665 && (t->type == TS_OVERVIEW || t->hex_width > 0 || t->hex_height > 0))) {
1666 log_error("Invalid darkness style set in tileset \"%s\".", t->name);
1667 goto ON_ERROR;
1669 t->darkness_layer = secfile_lookup_int_default(file, 0, "tilespec.darkness_layer");
1670 if (t->darkness_layer < 0 || t->darkness_layer >= TERRAIN_LAYER_COUNT) {
1671 tileset_error(LOG_ERROR, "Invalid darkness layer %d in tileset \"%s\"",
1672 t->darkness_layer, t->name);
1673 goto ON_ERROR;
1676 if (!secfile_lookup_int(file, &t->unit_flag_offset_x,
1677 "tilespec.unit_flag_offset_x")
1678 || !secfile_lookup_int(file, &t->unit_flag_offset_y,
1679 "tilespec.unit_flag_offset_y")
1680 || !secfile_lookup_int(file, &t->city_flag_offset_x,
1681 "tilespec.city_flag_offset_x")
1682 || !secfile_lookup_int(file, &t->city_flag_offset_y,
1683 "tilespec.city_flag_offset_y")
1684 || !secfile_lookup_int(file, &t->unit_offset_x,
1685 "tilespec.unit_offset_x")
1686 || !secfile_lookup_int(file, &t->unit_offset_y,
1687 "tilespec.unit_offset_y")
1688 || !secfile_lookup_int(file, &t->citybar_offset_y,
1689 "tilespec.citybar_offset_y")
1690 || !secfile_lookup_int(file, &t->tilelabel_offset_y,
1691 "tilespec.tilelabel_offset_y")
1692 || !secfile_lookup_int(file, &t->city_names_font_size,
1693 "tilespec.city_names_font_size")
1694 || !secfile_lookup_int(file, &t->city_productions_font_size,
1695 "tilespec.city_productions_font_size")) {
1696 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1697 goto ON_ERROR;
1700 set_city_names_font_sizes(t->city_names_font_size,
1701 t->city_productions_font_size);
1703 c = secfile_lookup_str(file, "tilespec.main_intro_file");
1704 t->main_intro_filename = tilespec_gfx_filename(c);
1705 log_debug("intro file %s", t->main_intro_filename);
1707 c = secfile_lookup_str(file, "tilespec.minimap_intro_file");
1708 t->minimap_intro_filename = tilespec_gfx_filename(c);
1709 log_debug("radar file %s", t->minimap_intro_filename);
1711 /* Terrain layer info. */
1712 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1713 struct tileset_layer *tslp = &t->layers[i];
1714 int j, k;
1716 tslp->match_types =
1717 (char **) secfile_lookup_str_vec(file, &tslp->match_count,
1718 "layer%d.match_types", i);
1719 for (j = 0; j < tslp->match_count; j++) {
1720 tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
1722 for (k = 0; k < j; k++) {
1723 if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
1724 tileset_error(LOG_FATAL, _("[layer%d] match_types: \"%s\" initial "
1725 "('%c') is not unique."),
1726 i, tslp->match_types[j], tslp->match_types[j][0]);
1727 /* FIXME: Returns NULL. */
1733 /* Tile drawing info. */
1734 sections = secfile_sections_by_name_prefix(file, TILE_SECTION_PREFIX);
1735 if (NULL == sections || 0 == section_list_size(sections)) {
1736 tileset_error(LOG_ERROR, _("No [%s] sections supported by tileset \"%s\"."),
1737 TILE_SECTION_PREFIX, fname);
1738 goto ON_ERROR;
1741 fc_assert(t->tile_hash == NULL);
1742 t->tile_hash = drawing_hash_new();
1744 section_list_iterate(sections, psection) {
1745 const char *sec_name = section_name(psection);
1746 struct drawing_data *draw = drawing_data_new(sec_name + spl);
1747 const char *sprite_type, *str;
1748 int l;
1750 draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
1751 sec_name);
1752 draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
1754 draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
1755 "%s.is_reversed",
1756 sec_name);
1757 draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
1758 sec_name);
1759 draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
1761 for (l = 0; l < draw->num_layers; l++) {
1762 struct drawing_layer *dlp = &draw->layer[l];
1763 struct tileset_layer *tslp = &t->layers[l];
1764 const char *match_type;
1765 const char **match_with;
1766 size_t count;
1768 dlp->is_tall
1769 = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
1770 sec_name, l);
1771 dlp->offset_x
1772 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
1773 sec_name, l);
1774 dlp->offset_y
1775 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
1776 sec_name, l);
1778 match_type = secfile_lookup_str_default(file, NULL,
1779 "%s.layer%d_match_type",
1780 sec_name, l);
1781 if (match_type) {
1782 int j;
1784 /* Determine our match_type. */
1785 for (j = 0; j < tslp->match_count; j++) {
1786 if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
1787 break;
1790 if (j >= tslp->match_count) {
1791 log_error("[%s] invalid match_type \"%s\".", sec_name, match_type);
1792 } else {
1793 dlp->match_index[dlp->match_indices++] = j;
1797 match_with = secfile_lookup_str_vec(file, &count,
1798 "%s.layer%d_match_with",
1799 sec_name, l);
1800 if (match_with) {
1801 int j, k;
1803 if (count > MAX_NUM_MATCH_WITH) {
1804 log_error("[%s] match_with has too many types (%d, max %d)",
1805 sec_name, (int) count, MAX_NUM_MATCH_WITH);
1806 count = MAX_NUM_MATCH_WITH;
1809 if (1 < dlp->match_indices) {
1810 log_error("[%s] previous match_with ignored.", sec_name);
1811 dlp->match_indices = 1;
1812 } else if (1 > dlp->match_indices) {
1813 log_error("[%s] missing match_type, using \"%s\".",
1814 sec_name, tslp->match_types[0]);
1815 dlp->match_index[0] = 0;
1816 dlp->match_indices = 1;
1819 for (k = 0; k < count; k++) {
1820 for (j = 0; j < tslp->match_count; j++) {
1821 if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
1822 break;
1825 if (j >= tslp->match_count) {
1826 log_error("[%s] layer%d_match_with: invalid \"%s\".",
1827 sec_name, l, match_with[k]);
1828 } else if (1 < count) {
1829 int m;
1831 for (m = 0; m < dlp->match_indices; m++) {
1832 if (dlp->match_index[m] == j) {
1833 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
1834 sec_name, l, match_with[k]);
1835 break;
1838 if (m >= dlp->match_indices) {
1839 dlp->match_index[dlp->match_indices++] = j;
1841 } else {
1842 dlp->match_index[dlp->match_indices++] = j;
1845 free(match_with);
1846 match_with = NULL;
1849 /* Check match_indices */
1850 switch (dlp->match_indices) {
1851 case 0:
1852 case 1:
1853 dlp->match_style = MATCH_NONE;
1854 break;
1855 case 2:
1856 if (dlp->match_index[0] == dlp->match_index[1] ) {
1857 dlp->match_style = MATCH_SAME;
1858 } else {
1859 dlp->match_style = MATCH_PAIR;
1861 break;
1862 default:
1863 dlp->match_style = MATCH_FULL;
1864 break;
1867 sprite_type
1868 = secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
1869 sec_name, l);
1870 dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
1872 switch (dlp->sprite_type) {
1873 case CELL_WHOLE:
1874 /* OK, no problem */
1875 break;
1876 case CELL_CORNER:
1877 if (dlp->is_tall
1878 || dlp->offset_x > 0
1879 || dlp->offset_y > 0) {
1880 log_error("[%s] layer %d: you cannot have tall terrain or\n"
1881 "a sprite offset with a cell-based drawing method.",
1882 sec_name, l);
1883 dlp->is_tall = FALSE;
1884 dlp->offset_x = dlp->offset_y = 0;
1886 break;
1890 str = secfile_lookup_str(file, "%s.mine_sprite", sec_name);
1891 if (NULL != str) {
1892 draw->mine_tag = fc_strdup(str);
1895 if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
1896 log_error("warning: duplicate tilespec entry [%s].", sec_name);
1897 goto ON_ERROR;
1899 } section_list_iterate_end;
1900 section_list_destroy(sections);
1901 sections = NULL;
1903 t->rstyle_hash = rstyle_hash_new();
1904 t->rivers = road_type_list_new();
1906 for (i = 0; (roadname = secfile_lookup_str_default(file, NULL,
1907 "roads.styles%d.name",
1908 i)); i++) {
1909 const char *style_name;
1910 enum roadstyle_id *style = fc_malloc(sizeof(enum roadstyle_id));
1911 char *name;
1913 style_name = secfile_lookup_str_default(file, "AllSeparate",
1914 "roads.styles%d.style", i);
1915 *style = roadstyle_id_by_name(style_name, fc_strcasecmp);
1916 if (!roadstyle_id_is_valid(*style)) {
1917 log_error("Unknown road style \"%s\" for road \"%s\"",
1918 style_name, roadname);
1919 FC_FREE(style);
1920 goto ON_ERROR;
1923 name = fc_malloc(strlen(roadname) + 1);
1924 strcpy(name, roadname);
1926 if (!rstyle_hash_insert(t->rstyle_hash, name, style)) {
1927 log_error("warning: duplicate roadstyle entry [%s].", roadname);
1928 FC_FREE(name);
1929 FC_FREE(style);
1930 goto ON_ERROR;
1934 spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
1935 "tilespec.files");
1936 if (NULL == spec_filenames || 0 == num_spec_files) {
1937 log_error("No tile graphics files specified in \"%s\"", fname);
1938 goto ON_ERROR;
1941 fc_assert(t->sprite_hash == NULL);
1942 t->sprite_hash = sprite_hash_new();
1943 for (i = 0; i < num_spec_files; i++) {
1944 struct specfile *sf = fc_malloc(sizeof(*sf));
1945 const char *dname;
1947 log_debug("spec file %s", spec_filenames[i]);
1949 sf->big_sprite = NULL;
1950 dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
1951 if (!dname) {
1952 if (verbose) {
1953 log_error("Can't find spec file \"%s\".", spec_filenames[i]);
1955 goto ON_ERROR;
1957 sf->file_name = fc_strdup(dname);
1958 scan_specfile(t, sf, duplicates_ok);
1960 specfile_list_prepend(t->specfiles, sf);
1962 free(spec_filenames);
1964 t->color_system = color_system_read(file);
1966 /* FIXME: remove this hack. */
1967 t->prefered_themes =
1968 (char **) secfile_lookup_str_vec(file, &num_prefered_themes,
1969 "tilespec.preferred_themes");
1970 if (num_prefered_themes <= 0) {
1971 t->prefered_themes =
1972 (char **) secfile_lookup_str_vec(file, &num_prefered_themes,
1973 "tilespec.prefered_themes");
1975 t->num_prefered_themes = num_prefered_themes;
1976 for (i = 0; i < t->num_prefered_themes; i++) {
1977 t->prefered_themes[i] = fc_strdup(t->prefered_themes[i]);
1980 secfile_check_unused(file);
1981 secfile_destroy(file);
1982 log_verbose("finished reading \"%s\".", fname);
1983 free(fname);
1985 return t;
1987 ON_ERROR:
1988 secfile_destroy(file);
1989 free(fname);
1990 tileset_free(t);
1991 if (NULL != sections) {
1992 section_list_destroy(sections);
1994 return NULL;
1997 /**********************************************************************
1998 Returns a text name for the citizen, as used in the tileset.
1999 ***********************************************************************/
2000 static const char *citizen_rule_name(enum citizen_category citizen)
2002 /* These strings are used in reading the tileset. Do not
2003 * translate. */
2004 switch (citizen) {
2005 case CITIZEN_HAPPY:
2006 return "happy";
2007 case CITIZEN_CONTENT:
2008 return "content";
2009 case CITIZEN_UNHAPPY:
2010 return "unhappy";
2011 case CITIZEN_ANGRY:
2012 return "angry";
2013 default:
2014 break;
2016 log_error("Unknown citizen type: %d.", (int) citizen);
2017 return NULL;
2020 /****************************************************************************
2021 Return a directional string for the cardinal directions. Normally the
2022 binary value 1000 will be converted into "n1e0s0w0". This is in a
2023 clockwise ordering.
2024 ****************************************************************************/
2025 static const char *cardinal_index_str(const struct tileset *t, int idx)
2027 static char c[64];
2028 int i;
2030 c[0] = '\0';
2031 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2032 int value = (idx >> i) & 1;
2034 cat_snprintf(c, sizeof(c), "%s%d",
2035 dir_get_tileset_name(t->cardinal_tileset_dirs[i]), value);
2038 return c;
2041 /****************************************************************************
2042 Do the same thing as cardinal_str, except including all valid directions.
2043 The returned string is a pointer to static memory.
2044 ****************************************************************************/
2045 static char *valid_index_str(const struct tileset *t, int index)
2047 static char c[64];
2048 int i;
2050 c[0] = '\0';
2051 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2052 int value = (index >> i) & 1;
2054 cat_snprintf(c, sizeof(c), "%s%d",
2055 dir_get_tileset_name(t->valid_tileset_dirs[i]), value);
2058 return c;
2061 /**************************************************************************
2062 Loads the sprite. If the sprite is already loaded a reference
2063 counter is increased. Can return NULL if the sprite couldn't be
2064 loaded.
2065 **************************************************************************/
2066 static struct sprite *load_sprite(struct tileset *t, const char *tag_name)
2068 struct small_sprite *ss;
2070 log_debug("load_sprite(tag='%s')", tag_name);
2071 /* Lookup information about where the sprite is found. */
2072 if (!sprite_hash_lookup(t->sprite_hash, tag_name, &ss)) {
2073 return NULL;
2076 fc_assert(ss->ref_count >= 0);
2078 if (!ss->sprite) {
2079 /* If the sprite hasn't been loaded already, then load it. */
2080 fc_assert(ss->ref_count == 0);
2081 if (ss->file) {
2082 ss->sprite = load_gfx_file(ss->file);
2083 if (!ss->sprite) {
2084 tileset_error(LOG_FATAL, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2085 ss->file, tag_name);
2087 } else {
2088 int sf_w, sf_h;
2090 ensure_big_sprite(ss->sf);
2091 get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2092 if (ss->x < 0 || ss->x + ss->width > sf_w
2093 || ss->y < 0 || ss->y + ss->height > sf_h) {
2094 tileset_error(LOG_ERROR, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2095 tag_name, ss->sf->file_name);
2096 return NULL;
2098 ss->sprite =
2099 crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height,
2100 NULL, -1, -1);
2104 /* Track the reference count so we know when to free the sprite. */
2105 ss->ref_count++;
2107 return ss->sprite;
2110 /**************************************************************************
2111 Create a sprite with the given color and tag.
2112 **************************************************************************/
2113 static struct sprite *create_plr_sprite(struct color *pcolor)
2115 struct sprite *sprite;
2117 fc_assert_ret_val(pcolor != NULL, NULL);
2119 sprite = create_sprite(128, 64, pcolor);
2121 return sprite;
2124 /**************************************************************************
2125 Unloads the sprite. Decrease the reference counter. If the last
2126 reference is removed the sprite is freed.
2127 **************************************************************************/
2128 static void unload_sprite(struct tileset *t, const char *tag_name)
2130 struct small_sprite *ss;
2132 sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
2133 fc_assert_ret(ss);
2134 fc_assert_ret(ss->ref_count >= 1);
2135 fc_assert_ret(ss->sprite);
2137 ss->ref_count--;
2139 if (ss->ref_count == 0) {
2140 /* Nobody's using the sprite anymore, so we should free it. We know
2141 * where to find it if we need it again. */
2142 log_debug("freeing sprite '%s'.", tag_name);
2143 free_sprite(ss->sprite);
2144 ss->sprite = NULL;
2148 /**************************************************************************
2149 Return TRUE iff the specified sprite exists in the tileset (whether
2150 or not it is currently loaded).
2151 **************************************************************************/
2152 static bool sprite_exists(const struct tileset *t, const char *tag_name)
2154 /* Lookup information about where the sprite is found. */
2155 return sprite_hash_lookup(t->sprite_hash, tag_name, NULL);
2158 /* Not very safe, but convenient: */
2159 #define SET_SPRITE(field, tag) \
2160 do { \
2161 t->sprites.field = load_sprite(t, tag); \
2162 if (t->sprites.field == NULL) { \
2163 tileset_error(LOG_FATAL, _("Sprite tag '%s' missing."), tag); \
2165 } while(FALSE)
2167 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2168 #define SET_SPRITE_ALT(field, tag, alt) \
2169 do { \
2170 t->sprites.field = load_sprite(t, tag); \
2171 if (!t->sprites.field) { \
2172 t->sprites.field = load_sprite(t, alt); \
2174 if (t->sprites.field == NULL) { \
2175 tileset_error(LOG_FATAL, _("Sprite tag '%s' and alternate '%s' are " \
2176 "both missing."), tag, alt); \
2178 } while(FALSE)
2180 /* Sets sprites.field to tag, or NULL if not available */
2181 #define SET_SPRITE_OPT(field, tag) \
2182 t->sprites.field = load_sprite(t, tag)
2184 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2185 do { \
2186 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2187 "sprite", #field); \
2188 } while (FALSE)
2190 /****************************************************************************
2191 Setup the graphics for specialist types.
2192 ****************************************************************************/
2193 void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
2195 /* Load the specialist sprite graphics. */
2196 char buffer[512];
2197 int j;
2198 const char *name = specialist_rule_name(specialist_by_number(id));
2199 const char *graphic_alt = specialist_by_number(id)->graphic_alt;
2201 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2202 /* Try rule name + index number */
2203 fc_snprintf(buffer, sizeof(buffer), "specialist.%s_%d", name, j);
2204 t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer);
2206 /* Break if no more index specific sprites are defined */
2207 if (!t->sprites.specialist[id].sprite[j]) {
2208 break;
2212 /* Nothing? Try the alt tag */
2213 if (j == 0) {
2214 t->sprites.specialist[id].sprite[j] = load_sprite(t, graphic_alt);
2216 if (t->sprites.specialist[id].sprite[j]) {
2217 j = 1;
2221 t->sprites.specialist[id].count = j;
2223 /* Still nothing? Give up. */
2224 if (j == 0) {
2225 tileset_error(LOG_FATAL, _("No graphics for specialist \"%s\"."), name);
2229 /****************************************************************************
2230 Setup the graphics for (non-specialist) citizen types.
2231 ****************************************************************************/
2232 static void tileset_setup_citizen_types(struct tileset *t)
2234 int i, j;
2235 char buffer[512];
2237 /* Load the citizen sprite graphics, no specialist. */
2238 for (i = 0; i < CITIZEN_LAST; i++) {
2239 const char *name = citizen_rule_name(i);
2241 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2242 fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
2243 t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer);
2244 if (!t->sprites.citizen[i].sprite[j]) {
2245 break;
2248 t->sprites.citizen[i].count = j;
2249 if (j == 0) {
2250 tileset_error(LOG_FATAL, _("No graphics for citizen \"%s\"."), name);
2255 /****************************************************************************
2256 Return the sprite in the city_sprite listing that corresponds to this
2257 city - based on city style and size.
2259 See also load_city_sprite, free_city_sprite.
2260 ****************************************************************************/
2261 static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
2262 const struct city *pcity)
2264 /* get style and match the best tile based on city size */
2265 int style = style_of_city(pcity);
2266 int num_thresholds;
2267 struct city_style_threshold *thresholds;
2268 int img_index;
2270 fc_assert_ret_val(style < city_sprite->num_styles, NULL);
2272 if (is_ocean_tile(pcity->tile)
2273 && city_sprite->styles[style].oceanic_num_thresholds != 0) {
2274 num_thresholds = city_sprite->styles[style].oceanic_num_thresholds;
2275 thresholds = city_sprite->styles[style].oceanic_thresholds;
2276 } else {
2277 num_thresholds = city_sprite->styles[style].land_num_thresholds;
2278 thresholds = city_sprite->styles[style].land_thresholds;
2281 if (num_thresholds == 0) {
2282 return NULL;
2285 /* Get the sprite with the index defined by the effects. */
2286 img_index = pcity->client.city_image;
2287 if (img_index == -100) {
2288 /* Server doesn't know right value as this is from old savegame.
2289 * Guess here based on *client* side information as was done in
2290 * versions where information was not saved to savegame - this should
2291 * give us right answer of what city looked like by the time it was
2292 * put under FoW. */
2293 img_index = get_city_bonus(pcity, EFT_CITY_IMAGE);
2295 img_index = CLIP(0, img_index, num_thresholds - 1);
2297 return thresholds[img_index].sprite;
2300 /****************************************************************************
2301 Allocates one threshold set for city sprite
2302 ****************************************************************************/
2303 static int load_city_thresholds_sprites(struct tileset *t, const char *tag,
2304 char *graphic, char *graphic_alt,
2305 struct city_style_threshold **thresholds)
2307 char buffer[128];
2308 char *gfx_in_use = graphic;
2309 int num_thresholds = 0;
2310 struct sprite *sprite;
2311 int size;
2313 *thresholds = NULL;
2315 for (size = 0; size < MAX_CITY_SIZE; size++) {
2316 fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
2317 gfx_in_use, tag, size);
2318 if ((sprite = load_sprite(t, buffer))) {
2319 num_thresholds++;
2320 *thresholds = fc_realloc(*thresholds, num_thresholds * sizeof(**thresholds));
2321 (*thresholds)[num_thresholds - 1].sprite = sprite;
2322 } else if (size == 0) {
2323 if (gfx_in_use == graphic) {
2324 /* Try again with graphic_alt. */
2325 size--;
2326 gfx_in_use = graphic_alt;
2327 } else {
2328 /* Don't load any others if the 0 element isn't there. */
2329 break;
2334 return num_thresholds;
2337 /****************************************************************************
2338 Allocates and loads a new city sprite from the given sprite tags.
2340 tag may be NULL.
2342 See also get_city_sprite, free_city_sprite.
2343 ****************************************************************************/
2344 static struct city_sprite *load_city_sprite(struct tileset *t,
2345 const char *tag)
2347 struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
2348 int style;
2350 /* Store number of styles we have allocated memory for.
2351 * game.control.styles_count might change if client disconnects from
2352 * server and connects new one. */
2353 city_sprite->num_styles = game.control.styles_count;
2354 city_sprite->styles = fc_malloc(city_sprite->num_styles
2355 * sizeof(*city_sprite->styles));
2357 for (style = 0; style < city_sprite->num_styles; style++) {
2358 city_sprite->styles[style].land_num_thresholds =
2359 load_city_thresholds_sprites(t, tag, city_styles[style].graphic,
2360 city_styles[style].graphic_alt,
2361 &city_sprite->styles[style].land_thresholds);
2362 city_sprite->styles[style].oceanic_num_thresholds =
2363 load_city_thresholds_sprites(t, tag, city_styles[style].oceanic_graphic,
2364 city_styles[style].oceanic_graphic_alt,
2365 &city_sprite->styles[style].oceanic_thresholds);
2368 return city_sprite;
2371 /****************************************************************************
2372 Frees a city sprite.
2374 See also get_city_sprite, load_city_sprite.
2375 ****************************************************************************/
2376 static void free_city_sprite(struct city_sprite *city_sprite)
2378 int style;
2380 if (!city_sprite) {
2381 return;
2383 for (style = 0; style < city_sprite->num_styles; style++) {
2384 if (city_sprite->styles[style].land_thresholds) {
2385 free(city_sprite->styles[style].land_thresholds);
2387 if (city_sprite->styles[style].oceanic_thresholds) {
2388 free(city_sprite->styles[style].oceanic_thresholds);
2391 free(city_sprite->styles);
2392 free(city_sprite);
2395 /**********************************************************************
2396 Initialize 'sprites' structure based on hardwired tags which
2397 freeciv always requires.
2398 ***********************************************************************/
2399 static void tileset_lookup_sprite_tags(struct tileset *t)
2401 char buffer[512], buffer2[512];
2402 const int W = t->normal_tile_width, H = t->normal_tile_height;
2403 int i, j, f;
2405 fc_assert_ret(t->sprite_hash != NULL);
2407 SET_SPRITE(treaty_thumb[0], "treaty.disagree_thumb_down");
2408 SET_SPRITE(treaty_thumb[1], "treaty.agree_thumb_up");
2410 for (j = 0; j < INDICATOR_COUNT; j++) {
2411 const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2413 for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2414 fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
2415 SET_SPRITE(indicator[j][i], buffer);
2419 SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
2420 SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
2421 SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
2422 if (t->type == TS_ISOMETRIC) {
2423 SET_SPRITE(dither_tile, "t.dither_tile");
2426 SET_SPRITE(mask.tile, "mask.tile");
2427 SET_SPRITE(mask.worked_tile, "mask.worked_tile");
2428 SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
2430 SET_SPRITE(tax_luxury, "s.tax_luxury");
2431 SET_SPRITE(tax_science, "s.tax_science");
2432 SET_SPRITE(tax_gold, "s.tax_gold");
2434 tileset_setup_citizen_types(t);
2436 for (i = 0; i < SPACESHIP_COUNT; i++) {
2437 const char *names[SPACESHIP_COUNT]
2438 = {"solar_panels", "life_support", "habitation",
2439 "structural", "fuel", "propulsion", "exhaust"};
2441 fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
2442 SET_SPRITE(spaceship[i], buffer);
2445 for (i = 0; i < CURSOR_LAST; i++) {
2446 for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2447 const char *names[CURSOR_LAST] =
2448 {"goto", "patrol", "paradrop", "nuke", "select",
2449 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2450 struct small_sprite *ss;
2452 fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2453 fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
2454 SET_SPRITE(cursor[i].frame[f], buffer);
2455 if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
2456 t->sprites.cursor[i].hot_x = ss->hot_x;
2457 t->sprites.cursor[i].hot_y = ss->hot_y;
2462 for (i = 0; i < ICON_COUNT; i++) {
2463 const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
2465 fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
2466 SET_SPRITE(icon[i], buffer);
2469 SET_SPRITE(explode.nuke, "explode.nuke");
2471 sprite_vector_init(&t->sprites.explode.unit);
2472 for (i = 0; ; i++) {
2473 struct sprite *sprite;
2475 fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
2476 sprite = load_sprite(t, buffer);
2477 if (!sprite) {
2478 break;
2480 sprite_vector_append(&t->sprites.explode.unit, sprite);
2483 SET_SPRITE(unit.auto_attack, "unit.auto_attack");
2484 SET_SPRITE(unit.auto_settler, "unit.auto_settler");
2485 SET_SPRITE(unit.auto_explore, "unit.auto_explore");
2486 SET_SPRITE(unit.fallout, "unit.fallout");
2487 SET_SPRITE(unit.fortified, "unit.fortified");
2488 SET_SPRITE(unit.fortifying, "unit.fortifying");
2489 SET_SPRITE(unit.go_to, "unit.goto");
2490 SET_SPRITE(unit.irrigate, "unit.irrigate");
2491 SET_SPRITE(unit.mine, "unit.mine");
2492 SET_SPRITE(unit.pillage, "unit.pillage");
2493 SET_SPRITE(unit.pollution, "unit.pollution");
2494 SET_SPRITE(unit.sentry, "unit.sentry");
2495 SET_SPRITE(unit.convert, "unit.convert");
2496 SET_SPRITE(unit.stack, "unit.stack");
2497 SET_SPRITE(unit.loaded, "unit.loaded");
2498 SET_SPRITE(unit.transform, "unit.transform");
2499 SET_SPRITE(unit.connect, "unit.connect");
2500 SET_SPRITE(unit.patrol, "unit.patrol");
2501 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
2502 fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
2503 fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
2504 fc_assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
2505 SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
2507 SET_SPRITE(unit.lowfuel, "unit.lowfuel");
2508 SET_SPRITE(unit.tired, "unit.tired");
2510 for(i=0; i<NUM_TILES_HP_BAR; i++) {
2511 fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
2512 SET_SPRITE(unit.hp_bar[i], buffer);
2515 for (i = 0; i < MAX_VET_LEVELS; i++) {
2516 /* Veteran level sprites are optional. For instance "green" units
2517 * usually have no special graphic. */
2518 fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
2519 t->sprites.unit.vet_lev[i] = load_sprite(t, buffer);
2522 t->sprites.unit.select[0] = NULL;
2523 if (sprite_exists(t, "unit.select0")) {
2524 for (i = 0; i < NUM_TILES_SELECT; i++) {
2525 fc_snprintf(buffer, sizeof(buffer), "unit.select%d", i);
2526 SET_SPRITE(unit.select[i], buffer);
2530 SET_SPRITE(citybar.shields, "citybar.shields");
2531 SET_SPRITE(citybar.food, "citybar.food");
2532 SET_SPRITE(citybar.trade, "citybar.trade");
2533 SET_SPRITE(citybar.occupied, "citybar.occupied");
2534 SET_SPRITE(citybar.background, "citybar.background");
2535 sprite_vector_init(&t->sprites.citybar.occupancy);
2536 for (i = 0; ; i++) {
2537 struct sprite *sprite;
2539 fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
2540 sprite = load_sprite(t, buffer);
2541 if (!sprite) {
2542 break;
2544 sprite_vector_append(&t->sprites.citybar.occupancy, sprite);
2546 if (t->sprites.citybar.occupancy.size < 2) {
2547 tileset_error(LOG_FATAL, _("Missing necessary citybar.occupancy_N sprites."));
2550 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2551 SET_EDITOR_SPRITE(erase);
2552 SET_EDITOR_SPRITE(brush);
2553 SET_EDITOR_SPRITE(copy);
2554 SET_EDITOR_SPRITE(paste);
2555 SET_EDITOR_SPRITE(copypaste);
2556 SET_EDITOR_SPRITE(startpos);
2557 SET_EDITOR_SPRITE(terrain);
2558 SET_EDITOR_SPRITE(terrain_resource);
2559 SET_EDITOR_SPRITE(terrain_special);
2560 SET_EDITOR_SPRITE(unit);
2561 SET_EDITOR_SPRITE(city);
2562 SET_EDITOR_SPRITE(vision);
2563 SET_EDITOR_SPRITE(territory);
2564 SET_EDITOR_SPRITE(properties);
2565 SET_EDITOR_SPRITE(road);
2566 SET_EDITOR_SPRITE(military_base);
2567 #undef SET_EDITOR_SPRITE
2569 SET_SPRITE(city.disorder, "city.disorder");
2571 for(i=0; i<NUM_TILES_DIGITS; i++) {
2572 fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
2573 SET_SPRITE(city.size[i], buffer);
2574 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
2575 SET_SPRITE_ALT(path.turns[i], buffer2, buffer);
2577 fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
2578 SET_SPRITE(city.size_tens[i], buffer);
2579 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
2580 SET_SPRITE_ALT(path.turns_tens[i], buffer2, buffer);
2582 fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
2583 SET_SPRITE_OPT(city.size_hundreds[i], buffer);
2584 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
2585 SET_SPRITE_ALT_OPT(path.turns_hundreds[i], buffer2, buffer);
2587 fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
2588 SET_SPRITE(city.tile_foodnum[i], buffer);
2589 fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
2590 SET_SPRITE(city.tile_shieldnum[i], buffer);
2591 fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
2592 SET_SPRITE(city.tile_tradenum[i], buffer);
2595 /* Must have at least one upkeep sprite per output type (and unhappy) */
2596 /* The rest are optional; we copy the previous sprite for unspecified ones */
2597 fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
2598 SET_SPRITE(upkeep.unhappy[0], buffer);
2599 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
2600 fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
2601 if (sprite_exists(t, buffer2)) {
2602 SET_SPRITE(upkeep.unhappy[i], buffer2);
2603 fc_strlcpy(buffer, buffer2, sizeof(buffer));
2604 } else {
2605 SET_SPRITE(upkeep.unhappy[i], buffer);
2608 output_type_iterate(o) {
2609 fc_snprintf(buffer, sizeof(buffer),
2610 "upkeep.%s", get_output_identifier(o));
2611 SET_SPRITE_OPT(upkeep.output[o][0], buffer);
2612 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
2613 fc_snprintf(buffer2, sizeof(buffer2),
2614 "upkeep.%s%d", get_output_identifier(o), i+1);
2615 if (sprite_exists(t, buffer2)) {
2616 SET_SPRITE(upkeep.output[o][i], buffer2);
2617 fc_strlcpy(buffer, buffer2, sizeof(buffer));
2618 } else {
2619 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
2620 SET_SPRITE_OPT(upkeep.output[o][i], buffer);
2623 } output_type_iterate_end;
2625 SET_SPRITE(user.attention, "user.attention");
2627 SET_SPRITE(tx.fallout, "tx.fallout");
2628 SET_SPRITE(tx.pollution, "tx.pollution");
2629 SET_SPRITE(tx.village, "tx.village");
2630 SET_SPRITE(tx.fog, "tx.fog");
2632 sprite_vector_init(&t->sprites.colors.overlays);
2633 for (i = 0; ; i++) {
2634 struct sprite *sprite;
2636 fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
2637 sprite = load_sprite(t, buffer);
2638 if (!sprite) {
2639 break;
2641 sprite_vector_append(&t->sprites.colors.overlays, sprite);
2643 if (i == 0) {
2644 tileset_error(LOG_FATAL, _("Missing overlay-color sprite colors.overlay_0."));
2647 /* Chop up and build the overlay graphics. */
2648 sprite_vector_reserve(&t->sprites.city.worked_tile_overlay,
2649 sprite_vector_size(&t->sprites.colors.overlays));
2650 sprite_vector_reserve(&t->sprites.city.unworked_tile_overlay,
2651 sprite_vector_size(&t->sprites.colors.overlays));
2652 for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
2653 struct sprite *color, *color_mask;
2654 struct sprite *worked, *unworked;
2656 color = *sprite_vector_get(&t->sprites.colors.overlays, i);
2657 color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0);
2658 worked = crop_sprite(color_mask, 0, 0, W, H,
2659 t->sprites.mask.worked_tile, 0, 0);
2660 unworked = crop_sprite(color_mask, 0, 0, W, H,
2661 t->sprites.mask.unworked_tile, 0, 0);
2662 free_sprite(color_mask);
2663 t->sprites.city.worked_tile_overlay.p[i] = worked;
2664 t->sprites.city.unworked_tile_overlay.p[i] = unworked;
2669 SET_SPRITE(grid.unavailable, "grid.unavailable");
2670 SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
2672 for (i = 0; i < EDGE_COUNT; i++) {
2673 int j;
2675 if (i == EDGE_UD && t->hex_width == 0) {
2676 continue;
2677 } else if (i == EDGE_LR && t->hex_height == 0) {
2678 continue;
2681 fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
2682 SET_SPRITE(grid.main[i], buffer);
2684 fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
2685 SET_SPRITE(grid.city[i], buffer);
2687 fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
2688 SET_SPRITE(grid.worked[i], buffer);
2690 fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
2691 SET_SPRITE(grid.selected[i], buffer);
2693 fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
2694 SET_SPRITE(grid.coastline[i], buffer);
2696 for (j = 0; j < 2; j++) {
2697 fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
2698 edge_name[i][j]);
2699 SET_SPRITE(grid.borders[i][j], buffer);
2704 /* We use direction-specific irrigation and farmland graphics, if they
2705 * are available. If not, we just fall back to the basic irrigation
2706 * graphics. */
2707 for (i = 0; i < t->num_index_cardinal; i++) {
2708 fc_snprintf(buffer, sizeof(buffer), "tx.s_irrigation_%s",
2709 cardinal_index_str(t, i));
2710 SET_SPRITE_ALT(tx.irrigation[i], buffer, "tx.irrigation");
2712 for (i = 0; i < t->num_index_cardinal; i++) {
2713 fc_snprintf(buffer, sizeof(buffer), "tx.s_farmland_%s",
2714 cardinal_index_str(t, i));
2715 SET_SPRITE_ALT(tx.farmland[i], buffer, "tx.farmland");
2718 switch (t->darkness_style) {
2719 case DARKNESS_NONE:
2720 /* Nothing. */
2721 break;
2722 case DARKNESS_ISORECT:
2724 /* Isometric: take a single tx.darkness tile and split it into 4. */
2725 struct sprite *darkness = load_sprite(t, "tx.darkness");
2726 const int W = t->normal_tile_width, H = t->normal_tile_height;
2727 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
2729 if (!darkness) {
2730 tileset_error(LOG_FATAL, _("Sprite tx.darkness missing."));
2732 for (i = 0; i < 4; i++) {
2733 t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
2734 offsets[i][1], W / 2, H / 2,
2735 NULL, 0, 0);
2738 break;
2739 case DARKNESS_CARD_SINGLE:
2740 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2741 enum direction8 dir = t->cardinal_tileset_dirs[i];
2743 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
2744 dir_get_tileset_name(dir));
2745 SET_SPRITE(tx.darkness[i], buffer);
2747 break;
2748 case DARKNESS_CARD_FULL:
2749 for(i = 1; i < t->num_index_cardinal; i++) {
2750 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
2751 cardinal_index_str(t, i));
2752 SET_SPRITE(tx.darkness[i], buffer);
2754 break;
2755 case DARKNESS_CORNER:
2756 t->sprites.tx.fullfog = fc_realloc(t->sprites.tx.fullfog,
2757 81 * sizeof(*t->sprites.tx.fullfog));
2758 for (i = 0; i < 81; i++) {
2759 /* Unknown, fog, known. */
2760 char ids[] = {'u', 'f', 'k'};
2761 char buf[512] = "t.fog";
2762 int values[4], j, k = i;
2764 for (j = 0; j < 4; j++) {
2765 values[j] = k % 3;
2766 k /= 3;
2768 cat_snprintf(buf, sizeof(buf), "_%c", ids[values[j]]);
2770 fc_assert(k == 0);
2772 t->sprites.tx.fullfog[i] = load_sprite(t, buf);
2774 break;
2777 /* no other place to initialize these variables */
2778 sprite_vector_init(&t->sprites.nation_flag);
2779 sprite_vector_init(&t->sprites.nation_shield);
2782 /**************************************************************************
2783 Load sprites of one river type.
2784 **************************************************************************/
2785 static bool load_river_sprites(struct tileset *t,
2786 struct river_sprites *store, const char *tag_pfx)
2788 int i;
2789 const char dir_char[] = "nsew";
2790 char buffer[512];
2792 for (i = 0; i < t->num_index_cardinal; i++) {
2793 fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
2794 tag_pfx, cardinal_index_str(t, i));
2795 store->spec[i] = load_sprite(t, buffer);
2796 if (store->spec[i] == NULL) {
2797 return FALSE;
2801 for (i = 0; i < 4; i++) {
2802 fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%c",
2803 tag_pfx, dir_char[i]);
2804 store->outlet[i] = load_sprite(t, buffer);
2805 if (store->outlet[i] == NULL) {
2806 return FALSE;
2810 return TRUE;
2813 /**************************************************************************
2814 Frees any internal buffers which are created by load_sprite. Should
2815 be called after the last (for a given period of time) load_sprite
2816 call. This saves a fair amount of memory, but it will take extra time
2817 the next time we start loading sprites again.
2818 **************************************************************************/
2819 void finish_loading_sprites(struct tileset *t)
2821 specfile_list_iterate(t->specfiles, sf) {
2822 if (sf->big_sprite) {
2823 free_sprite(sf->big_sprite);
2824 sf->big_sprite = NULL;
2826 } specfile_list_iterate_end;
2829 /**********************************************************************
2830 Load the tiles; requires tilespec_read_toplevel() called previously.
2831 Leads to tile_sprites being allocated and filled with pointers
2832 to sprites. Also sets up and populates sprite_hash, and calls func
2833 to initialize 'sprites' structure.
2834 ***********************************************************************/
2835 void tileset_load_tiles(struct tileset *t)
2837 tileset_lookup_sprite_tags(t);
2838 finish_loading_sprites(t);
2841 /**********************************************************************
2842 Lookup sprite to match tag, or else to match alt if don't find,
2843 or else return NULL, and emit log message.
2844 ***********************************************************************/
2845 struct sprite *tiles_lookup_sprite_tag_alt(struct tileset *t,
2846 enum log_level level,
2847 const char *tag, const char *alt,
2848 const char *what,
2849 const char *name)
2851 struct sprite *sp;
2853 /* (should get sprite_hash before connection) */
2854 fc_assert_ret_val_msg(NULL != t->sprite_hash, NULL,
2855 "attempt to lookup for %s \"%s\" before "
2856 "sprite_hash setup", what, name);
2858 sp = load_sprite(t, tag);
2859 if (sp) return sp;
2861 sp = load_sprite(t, alt);
2862 if (sp) {
2863 log_verbose("Using alternate graphic \"%s\" "
2864 "(instead of \"%s\") for %s \"%s\".",
2865 alt, tag, what, name);
2866 return sp;
2868 if (level <= LOG_ERROR) {
2869 tileset_error(level, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
2870 tag, alt, what, name);
2871 } else {
2872 log_base(level, "Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\".",
2873 tag, alt, what, name);
2876 return NULL;
2879 /**********************************************************************
2880 Helper function to load sprite for one unit orientation
2881 ***********************************************************************/
2882 static bool tileset_setup_unit_direction(struct tileset *t,
2883 int uidx,
2884 const char *base_str,
2885 enum direction8 dir,
2886 const char *dirsuffix)
2888 char buf[2048];
2890 fc_snprintf(buf, sizeof(buf), "%s_%s", base_str, dirsuffix);
2892 /* We don't use _alt graphics here, as that could lead to loading
2893 * real icon gfx, but alternative orientation gfx. Tileset author
2894 * probably meant icon gfx to be used as fallback for all orientations */
2895 t->sprites.units.facing[uidx][dir] = load_sprite(t, buf);
2897 if (t->sprites.units.facing[uidx][dir] != NULL) {
2898 return TRUE;
2901 return FALSE;
2904 /**********************************************************************
2905 Try to setup all unit type sprites from single tag
2906 ***********************************************************************/
2907 bool static tileset_setup_unit_type_from_tag(struct tileset *t,
2908 int uidx, const char *tag)
2910 bool facing_sprites = TRUE;
2912 t->sprites.units.icon[uidx] = load_sprite(t, tag);
2914 #define LOAD_FACING_SPRITE(dir, dname) \
2915 if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
2916 facing_sprites = FALSE; \
2919 LOAD_FACING_SPRITE(DIR8_NORTHWEST, "nw");
2920 LOAD_FACING_SPRITE(DIR8_NORTH, "n");
2921 LOAD_FACING_SPRITE(DIR8_NORTHEAST, "ne");
2922 LOAD_FACING_SPRITE(DIR8_WEST, "w");
2923 LOAD_FACING_SPRITE(DIR8_EAST, "e");
2924 LOAD_FACING_SPRITE(DIR8_SOUTHWEST, "sw");
2925 LOAD_FACING_SPRITE(DIR8_SOUTH, "s");
2926 LOAD_FACING_SPRITE(DIR8_SOUTHEAST, "se");
2928 if (!facing_sprites && t->sprites.units.icon[uidx] == NULL) {
2929 /* Neither icon gfx or orientation sprites */
2930 return FALSE;
2933 return TRUE;
2935 #undef LOAD_FACING_SPRITE
2938 /**********************************************************************
2939 Set unit_type sprite value; should only happen after
2940 tilespec_load_tiles().
2941 ***********************************************************************/
2942 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
2944 int uidx = utype_index(ut);
2946 if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
2947 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
2948 tileset_error(LOG_FATAL, _("Missing %s unit tag \"%s\" and alternative \"%s\"."),
2949 utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
2953 /**********************************************************************
2954 Set improvement_type sprite value; should only happen after
2955 tilespec_load_tiles().
2956 ***********************************************************************/
2957 void tileset_setup_impr_type(struct tileset *t,
2958 struct impr_type *pimprove)
2960 t->sprites.building[improvement_index(pimprove)] =
2961 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, pimprove->graphic_str,
2962 pimprove->graphic_alt, "improvement",
2963 improvement_rule_name(pimprove));
2965 /* should maybe do something if NULL, eg generic default? */
2968 /**********************************************************************
2969 Set tech_type sprite value; should only happen after
2970 tilespec_load_tiles().
2971 ***********************************************************************/
2972 void tileset_setup_tech_type(struct tileset *t,
2973 struct advance *padvance)
2975 if (valid_advance(padvance)) {
2976 t->sprites.tech[advance_index(padvance)] =
2977 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, padvance->graphic_str,
2978 padvance->graphic_alt, "technology",
2979 advance_rule_name(padvance));
2981 /* should maybe do something if NULL, eg generic default? */
2982 } else {
2983 t->sprites.tech[advance_index(padvance)] = NULL;
2987 /****************************************************************************
2988 Set resource sprite values; should only happen after
2989 tilespec_load_tiles().
2990 ****************************************************************************/
2991 void tileset_setup_resource(struct tileset *t,
2992 const struct resource *presource)
2994 fc_assert_ret(NULL != presource);
2995 t->sprites.resource[resource_index(presource)] =
2996 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, presource->graphic_str,
2997 presource->graphic_alt, "resource",
2998 resource_rule_name(presource));
3001 /****************************************************************************
3002 Set road sprite values; should only happen after
3003 tilespec_load_tiles().
3004 ****************************************************************************/
3005 void tileset_setup_road(struct tileset *t,
3006 struct road_type *proad)
3008 char full_tag_name[MAX_LEN_NAME + strlen("_isolated")];
3009 char full_alt_name[MAX_LEN_NAME + strlen("_isolated")];
3010 const int id = road_index(proad);
3011 int i;
3012 enum roadstyle_id *roadstyle;
3014 if (!rstyle_hash_lookup(t->rstyle_hash, proad->graphic_str,
3015 &roadstyle)
3016 && !rstyle_hash_lookup(t->rstyle_hash, proad->graphic_alt,
3017 &roadstyle)) {
3018 tileset_error(LOG_FATAL, _("No roadstyle for \"%s\" or \"%s\"."),
3019 proad->graphic_str,
3020 proad->graphic_alt);
3023 t->sprites.roads[id].roadstyle = *roadstyle;
3025 if (*roadstyle == RSTYLE_RIVER) {
3026 road_type_list_append(t->rivers, proad);
3029 /* Isolated road graphics are used by RSTYLE_ALL_SEPARATE and
3030 RSTYLE_PARITY_COMBINED. */
3031 if (*roadstyle == RSTYLE_ALL_SEPARATE || *roadstyle == RSTYLE_PARITY_COMBINED) {
3032 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3033 "%s_isolated", proad->graphic_str);
3034 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3035 "%s_isolated", proad->graphic_alt);
3037 SET_SPRITE_ALT(roads[id].isolated, full_tag_name, full_alt_name);
3040 if (*roadstyle == RSTYLE_ALL_SEPARATE) {
3041 /* RSTYLE_ALL_SEPARATE has just 8 additional sprites for each road type:
3042 * one going off in each direction. */
3043 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3044 enum direction8 dir = t->valid_tileset_dirs[i];
3045 const char *dir_name = dir_get_tileset_name(dir);
3047 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3048 "%s_%s", proad->graphic_str, dir_name);
3049 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3050 "%s_%s", proad->graphic_alt, dir_name);
3052 SET_SPRITE_ALT(roads[id].u.dir[i], full_tag_name, full_alt_name);
3054 } else if (*roadstyle == RSTYLE_PARITY_COMBINED) {
3055 int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
3057 /* RSTYLE_PARITY_COMBINED has 32 additional sprites for each road type:
3058 * 16 each for cardinal and diagonal directions. Each set
3059 * of 16 provides a NSEW-indexed sprite to provide connectors for
3060 * all rails in the cardinal/diagonal directions. The 0 entry is
3061 * unused (the "isolated" sprite is used instead). */
3063 for (i = 1; i < num_index; i++) {
3064 char c[64] = "", d[64] = "";
3066 for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
3067 int value = (i >> j) & 1;
3069 cat_snprintf(c, sizeof(c), "%s%d",
3070 dir_get_tileset_name(t->valid_tileset_dirs[2 * j]),
3071 value);
3072 cat_snprintf(d, sizeof(d), "%s%d",
3073 dir_get_tileset_name(t->valid_tileset_dirs[2 * j + 1]),
3074 value);
3077 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3078 "%s_c_%s", proad->graphic_str, c);
3079 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3080 "%s_c_%s", proad->graphic_alt, c);
3082 SET_SPRITE_ALT(roads[id].u.combo.even[i], full_tag_name, full_alt_name);
3084 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3085 "%s_d_%s", proad->graphic_str, d);
3086 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3087 "%s_d_%s", proad->graphic_alt, d);
3089 SET_SPRITE_ALT(roads[id].u.combo.odd[i], full_tag_name, full_alt_name);
3091 } else if (*roadstyle == RSTYLE_ALL_COMBINED) {
3092 /* RSTYLE_ALL_COMBINED includes 256 sprites, one for every possibility.
3093 * Just go around clockwise, with all combinations. */
3094 for (i = 0; i < t->num_index_valid; i++) {
3095 char *idx_str = valid_index_str(t, i);
3097 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3098 "%s_%s", proad->graphic_str, idx_str);
3099 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3100 "%s_%s", proad->graphic_alt, idx_str);
3102 SET_SPRITE_ALT(roads[id].u.total[i], full_tag_name, full_alt_name);
3104 } else if (*roadstyle == RSTYLE_RIVER) {
3105 if (!load_river_sprites(t, &t->sprites.roads[id].u.rivers,
3106 proad->graphic_str)) {
3107 if (!load_river_sprites(t, &t->sprites.roads[id].u.rivers,
3108 proad->graphic_alt)) {
3109 tileset_error(LOG_FATAL, _("Cannot load river \"%s\" or \"%s\""),
3110 proad->graphic_str, proad->graphic_alt);
3113 } else {
3114 fc_assert(FALSE);
3117 /* Corner road graphics are used by RSTYLE_ALL_SEPARATE and
3118 * RSTYLE_PARITY_COMBINED. */
3119 if (*roadstyle == RSTYLE_ALL_SEPARATE || *roadstyle == RSTYLE_PARITY_COMBINED) {
3120 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3121 enum direction8 dir = t->valid_tileset_dirs[i];
3123 if (!is_cardinal_tileset_dir(t, dir)) {
3124 const char *dtn = dir_get_tileset_name(dir);
3126 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3127 "%s_c_%s", proad->graphic_str, dtn);
3128 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3129 "%s_c_%s", proad->graphic_alt, dtn);
3131 SET_SPRITE_ALT_OPT(roads[id].corner[dir], full_tag_name, full_alt_name);
3136 t->sprites.roads[id].activity = load_sprite(t, proad->activity_gfx);
3137 if (t->sprites.roads[id].activity == NULL) {
3138 t->sprites.roads[id].activity = load_sprite(t, proad->act_gfx_alt);
3139 if (t->sprites.roads[id].activity == NULL) {
3140 tileset_error(LOG_FATAL, _("Missing %s building activity tag \"%s\" and alternative \"%s\"."),
3141 road_rule_name(proad), proad->activity_gfx, proad->act_gfx_alt);
3146 /****************************************************************************
3147 Set base sprite values; should only happen after
3148 tilespec_load_tiles().
3149 ****************************************************************************/
3150 void tileset_setup_base(struct tileset *t,
3151 const struct base_type *pbase)
3153 char full_tag_name[MAX_LEN_NAME + strlen("_fg")];
3154 const int id = base_index(pbase);
3156 fc_assert_ret(id >= 0 && id < base_count());
3158 sz_strlcpy(full_tag_name, pbase->graphic_str);
3159 strcat(full_tag_name, "_bg");
3160 t->sprites.bases[id].background = load_sprite(t, full_tag_name);
3162 sz_strlcpy(full_tag_name, pbase->graphic_str);
3163 strcat(full_tag_name, "_mg");
3164 t->sprites.bases[id].middleground = load_sprite(t, full_tag_name);
3166 sz_strlcpy(full_tag_name, pbase->graphic_str);
3167 strcat(full_tag_name, "_fg");
3168 t->sprites.bases[id].foreground = load_sprite(t, full_tag_name);
3170 if (t->sprites.bases[id].background == NULL
3171 && t->sprites.bases[id].middleground == NULL
3172 && t->sprites.bases[id].foreground == NULL) {
3173 /* No primary graphics at all. Try alternative */
3174 log_verbose("Using alternate graphic \"%s\" "
3175 "(instead of \"%s\") for base \"%s\".",
3176 pbase->graphic_alt, pbase->graphic_str,
3177 base_rule_name(pbase));
3179 sz_strlcpy(full_tag_name, pbase->graphic_alt);
3180 strcat(full_tag_name, "_bg");
3181 t->sprites.bases[id].background = load_sprite(t, full_tag_name);
3183 sz_strlcpy(full_tag_name, pbase->graphic_alt);
3184 strcat(full_tag_name, "_mg");
3185 t->sprites.bases[id].middleground = load_sprite(t, full_tag_name);
3187 sz_strlcpy(full_tag_name, pbase->graphic_alt);
3188 strcat(full_tag_name, "_fg");
3189 t->sprites.bases[id].foreground = load_sprite(t, full_tag_name);
3191 if (t->sprites.bases[id].background == NULL
3192 && t->sprites.bases[id].middleground == NULL
3193 && t->sprites.bases[id].foreground == NULL) {
3194 /* Cannot find alternative graphics either */
3195 tileset_error(LOG_FATAL, _("No graphics for base \"%s\" at all!"),
3196 base_rule_name(pbase));
3200 t->sprites.bases[id].activity = load_sprite(t, pbase->activity_gfx);
3201 if (t->sprites.bases[id].activity == NULL) {
3202 t->sprites.bases[id].activity = load_sprite(t, pbase->act_gfx_alt);
3203 if (t->sprites.bases[id].activity == NULL) {
3204 tileset_error(LOG_FATAL, _("Missing %s building activity tag \"%s\" and alternative \"%s\"."),
3205 base_rule_name(pbase), pbase->activity_gfx, pbase->act_gfx_alt);
3211 /**********************************************************************
3212 Set tile_type sprite values; should only happen after
3213 tilespec_load_tiles().
3214 ***********************************************************************/
3215 void tileset_setup_tile_type(struct tileset *t,
3216 const struct terrain *pterrain)
3218 struct drawing_data *draw;
3219 struct sprite *sprite;
3220 char buffer[MAX_LEN_NAME + 20];
3221 int i, l;
3223 if (0 == strlen(terrain_rule_name(pterrain))) {
3224 return;
3227 if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
3228 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
3229 tileset_error(LOG_FATAL, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3230 terrain_rule_name(pterrain), pterrain->graphic_str,
3231 pterrain->graphic_alt);
3234 /* Set up each layer of the drawing. */
3235 for (l = 0; l < draw->num_layers; l++) {
3236 struct drawing_layer *dlp = &draw->layer[l];
3237 struct tileset_layer *tslp = &t->layers[l];
3238 sprite_vector_init(&dlp->base);
3239 sprite_vector_init(&dlp->allocated);
3241 switch (dlp->sprite_type) {
3242 case CELL_WHOLE:
3243 switch (dlp->match_style) {
3244 case MATCH_NONE:
3245 /* Load whole sprites for this tile. */
3246 for (i = 0; ; i++) {
3247 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
3248 l, draw->name, i + 1);
3249 sprite = load_sprite(t, buffer);
3250 if (!sprite) {
3251 break;
3253 sprite_vector_reserve(&dlp->base, i + 1);
3254 dlp->base.p[i] = sprite;
3256 /* check for base sprite, allowing missing sprites above base */
3257 if (0 == i && 0 == l) {
3258 tileset_error(LOG_FATAL, _("Missing base sprite tag \"%s\"."), buffer);
3260 break;
3261 case MATCH_SAME:
3262 /* Load 16 cardinally-matched sprites. */
3263 for (i = 0; i < t->num_index_cardinal; i++) {
3264 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
3265 l, draw->name, cardinal_index_str(t, i));
3266 dlp->match[i] =
3267 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3268 "matched terrain",
3269 terrain_rule_name(pterrain));
3271 break;
3272 case MATCH_PAIR:
3273 case MATCH_FULL:
3274 fc_assert(FALSE); /* not yet defined */
3275 break;
3277 break;
3278 case CELL_CORNER:
3280 const int count = dlp->match_indices;
3281 int number = NUM_CORNER_DIRS;
3283 switch (dlp->match_style) {
3284 case MATCH_NONE:
3285 /* do nothing */
3286 break;
3287 case MATCH_PAIR:
3288 case MATCH_SAME:
3289 /* N directions (NSEW) * 3 dimensions of matching */
3290 fc_assert(count == 2);
3291 number = NUM_CORNER_DIRS * 2 * 2 * 2;
3292 break;
3293 case MATCH_FULL:
3294 default:
3295 /* N directions (NSEW) * 3 dimensions of matching */
3296 /* could use exp() or expi() here? */
3297 number = NUM_CORNER_DIRS * count * count * count;
3298 break;
3301 dlp->cells
3302 = fc_calloc(number, sizeof(*dlp->cells));
3304 for (i = 0; i < number; i++) {
3305 enum direction4 dir = i % NUM_CORNER_DIRS;
3306 int value = i / NUM_CORNER_DIRS;
3308 switch (dlp->match_style) {
3309 case MATCH_NONE:
3310 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
3311 l, draw->name, direction4letters[dir]);
3312 dlp->cells[i] =
3313 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3314 "cell terrain",
3315 terrain_rule_name(pterrain));
3316 break;
3317 case MATCH_SAME:
3318 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
3319 l, draw->name, direction4letters[dir],
3320 (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
3321 dlp->cells[i] =
3322 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3323 "same cell terrain",
3324 terrain_rule_name(pterrain));
3325 break;
3326 case MATCH_PAIR:
3327 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
3328 l, draw->name, direction4letters[dir],
3329 tslp->match_types[dlp->match_index[(value) & 1]][0],
3330 tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
3331 tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
3332 dlp->cells[i] =
3333 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3334 "cell pair terrain",
3335 terrain_rule_name(pterrain));
3336 break;
3337 case MATCH_FULL:
3339 int this = dlp->match_index[0];
3340 int n, s, e, w;
3341 int v1, v2, v3;
3343 v1 = dlp->match_index[value % count];
3344 value /= count;
3345 v2 = dlp->match_index[value % count];
3346 value /= count;
3347 v3 = dlp->match_index[value % count];
3349 fc_assert(v1 < count && v2 < count && v3 < count);
3351 /* Assume merged cells. This should be a separate option. */
3352 switch (dir) {
3353 case DIR4_NORTH:
3354 s = this;
3355 w = v1;
3356 n = v2;
3357 e = v3;
3358 break;
3359 case DIR4_EAST:
3360 w = this;
3361 n = v1;
3362 e = v2;
3363 s = v3;
3364 break;
3365 case DIR4_SOUTH:
3366 n = this;
3367 e = v1;
3368 s = v2;
3369 w = v3;
3370 break;
3371 case DIR4_WEST:
3372 default: /* avoid warnings */
3373 e = this;
3374 s = v1;
3375 w = v2;
3376 n = v3;
3377 break;
3380 /* Use first character of match_types,
3381 * already checked for uniqueness. */
3382 fc_snprintf(buffer, sizeof(buffer),
3383 "t.l%d.cellgroup_%c_%c_%c_%c", l,
3384 tslp->match_types[n][0], tslp->match_types[e][0],
3385 tslp->match_types[s][0], tslp->match_types[w][0]);
3386 sprite = load_sprite(t, buffer);
3388 if (sprite) {
3389 /* Crop the sprite to separate this cell. */
3390 int vec_size = sprite_vector_size(&dlp->allocated);
3392 const int W = t->normal_tile_width;
3393 const int H = t->normal_tile_height;
3394 int x[4] = {W / 4, W / 4, 0, W / 2};
3395 int y[4] = {H / 2, 0, H / 4, H / 4};
3396 int xo[4] = {0, 0, -W / 2, W / 2};
3397 int yo[4] = {H / 2, -H / 2, 0, 0};
3399 sprite = crop_sprite(sprite,
3400 x[dir], y[dir], W / 2, H / 2,
3401 t->sprites.mask.tile,
3402 xo[dir], yo[dir]);
3404 /* We allocated new sprite with crop_sprite. Store its
3405 * address so we can free it. */
3406 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
3407 dlp->allocated.p[vec_size] = sprite;
3408 } else {
3409 log_error("Terrain graphics tag \"%s\" missing.", buffer);
3412 dlp->cells[i] = sprite;
3414 break;
3418 break;
3422 /* try an optional special name */
3423 fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
3424 draw->blender =
3425 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, buffer, "",
3426 "blend terrain",
3427 terrain_rule_name(pterrain));
3429 if (draw->blending > 0) {
3430 const int l = draw->blending - 1;
3432 if (NULL == draw->blender) {
3433 int i = 0;
3434 /* try an already loaded base */
3435 while (NULL == draw->blender
3436 && i < draw->blending
3437 && 0 < draw->layer[i].base.size) {
3438 draw->blender = draw->layer[i++].base.p[0];
3442 if (NULL == draw->blender) {
3443 /* try an unloaded base name */
3444 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", l, draw->name);
3445 draw->blender =
3446 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3447 "base (blend) terrain",
3448 terrain_rule_name(pterrain));
3452 if (NULL != draw->blender) {
3453 /* Set up blending sprites. This only works in iso-view! */
3454 const int W = t->normal_tile_width;
3455 const int H = t->normal_tile_height;
3456 const int offsets[4][2] = {
3457 {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
3459 enum direction4 dir = 0;
3461 for (; dir < 4; dir++) {
3462 draw->blend[dir] = crop_sprite(draw->blender,
3463 offsets[dir][0], offsets[dir][1],
3464 W / 2, H / 2,
3465 t->sprites.dither_tile, 0, 0);
3469 if (draw->mine_tag) {
3470 draw->mine = load_sprite(t, draw->mine_tag);
3471 } else {
3472 draw->mine = NULL;
3475 t->sprites.drawing[terrain_index(pterrain)] = draw;
3478 /**********************************************************************
3479 Set government sprite value; should only happen after
3480 tilespec_load_tiles().
3481 ***********************************************************************/
3482 void tileset_setup_government(struct tileset *t,
3483 struct government *gov)
3485 t->sprites.government[government_index(gov)] =
3486 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, gov->graphic_str,
3487 gov->graphic_alt, "government",
3488 government_rule_name(gov));
3490 /* should probably do something if NULL, eg generic default? */
3493 /**********************************************************************
3494 Set nation flag sprite value; should only happen after
3495 tilespec_load_tiles().
3496 ***********************************************************************/
3497 void tileset_setup_nation_flag(struct tileset *t,
3498 struct nation_type *nation)
3500 char *tags[] = {nation->flag_graphic_str,
3501 nation->flag_graphic_alt,
3502 "unknown", NULL};
3503 int i;
3504 struct sprite *flag = NULL, *shield = NULL;
3505 char buf[1024];
3507 for (i = 0; tags[i] && !flag; i++) {
3508 fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
3509 flag = load_sprite(t, buf);
3511 for (i = 0; tags[i] && !shield; i++) {
3512 fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
3513 shield = load_sprite(t, buf);
3515 if (!flag || !shield) {
3516 /* Should never get here because of the f.unknown fallback. */
3517 tileset_error(LOG_FATAL, _("Nation %s: no national flag."), nation_rule_name(nation));
3520 sprite_vector_reserve(&t->sprites.nation_flag, nation_count());
3521 t->sprites.nation_flag.p[nation_index(nation)] = flag;
3523 sprite_vector_reserve(&t->sprites.nation_shield, nation_count());
3524 t->sprites.nation_shield.p[nation_index(nation)] = shield;
3527 /**********************************************************************
3528 Return the flag graphic to be used by the city.
3529 ***********************************************************************/
3530 struct sprite *get_city_flag_sprite(const struct tileset *t,
3531 const struct city *pcity)
3533 return get_nation_flag_sprite(t, nation_of_city(pcity));
3536 /**********************************************************************
3537 Return a sprite for the national flag for this unit.
3538 ***********************************************************************/
3539 static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
3540 const struct unit *punit)
3542 struct nation_type *pnation = nation_of_unit(punit);
3544 if (draw_unit_shields) {
3545 return t->sprites.nation_shield.p[nation_index(pnation)];
3546 } else {
3547 return t->sprites.nation_flag.p[nation_index(pnation)];
3551 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
3552 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
3554 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
3555 (fc_assert(s != NULL), \
3556 sprs->sprite = s, \
3557 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
3558 sprs->offset_x = x_offset, \
3559 sprs->offset_y = y_offset, \
3560 sprs++)
3561 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
3562 #define ADD_SPRITE_FULL(s) \
3563 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
3565 /**************************************************************************
3566 Assemble some data that is used in building the tile sprite arrays.
3567 (map_x, map_y) : the (normalized) map position
3568 The values we fill in:
3569 tterrain_near : terrain types of all adjacent terrain
3570 tspecial_near : specials of all adjacent terrain
3571 **************************************************************************/
3572 static void build_tile_data(const struct tile *ptile,
3573 struct terrain *pterrain,
3574 struct terrain **tterrain_near,
3575 bv_special *tspecial_near,
3576 bv_roads *troad_near)
3578 enum direction8 dir;
3580 /* Loop over all adjacent tiles. We should have an iterator for this. */
3581 for (dir = 0; dir < 8; dir++) {
3582 struct tile *tile1 = mapstep(ptile, dir);
3584 if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
3585 struct terrain *terrain1 = tile_terrain(tile1);
3587 if (NULL != terrain1) {
3588 tterrain_near[dir] = terrain1;
3589 tspecial_near[dir] = tile_specials(tile1);
3590 troad_near[dir] = tile_roads(tile1);
3591 continue;
3593 log_error("build_tile_data() tile (%d,%d) has no terrain!",
3594 TILE_XY(tile1));
3596 /* At the edges of the (known) map, pretend the same terrain continued
3597 * past the edge of the map. */
3598 tterrain_near[dir] = pterrain;
3599 BV_CLR_ALL(tspecial_near[dir]);
3600 BV_CLR_ALL(troad_near[dir]);
3604 /**********************************************************************
3605 Fill in the sprite array for the unit type.
3606 ***********************************************************************/
3607 static int fill_unit_type_sprite_array(const struct tileset *t,
3608 struct drawn_sprite *sprs,
3609 const struct unit_type *putype,
3610 enum direction8 facing)
3612 struct drawn_sprite *save_sprs = sprs;
3613 struct sprite *uspr = get_unittype_sprite(t, putype, facing, FALSE);
3615 ADD_SPRITE(uspr, TRUE,
3616 FULL_TILE_X_OFFSET + t->unit_offset_x,
3617 FULL_TILE_Y_OFFSET + t->unit_offset_y);
3619 return sprs - save_sprs;
3622 /**********************************************************************
3623 Fill in the sprite array for the unit.
3624 ***********************************************************************/
3625 static int fill_unit_sprite_array(const struct tileset *t,
3626 struct drawn_sprite *sprs,
3627 const struct unit *punit,
3628 bool stack, bool backdrop)
3630 struct drawn_sprite *save_sprs = sprs;
3631 int ihp;
3632 struct unit_type *ptype = unit_type(punit);
3634 if (backdrop) {
3635 if (!solid_color_behind_units) {
3636 ADD_SPRITE(get_unit_nation_flag_sprite(t, punit), TRUE,
3637 FULL_TILE_X_OFFSET + t->unit_flag_offset_x,
3638 FULL_TILE_Y_OFFSET + t->unit_flag_offset_y);
3639 } else {
3640 /* Taken care of in the LAYER_BACKGROUND. */
3644 /* Add the sprite for the unit type. */
3645 sprs += fill_unit_type_sprite_array(t, sprs, ptype,
3646 punit->facing);
3648 if (t->sprites.unit.loaded && unit_transported(punit)) {
3649 ADD_SPRITE_FULL(t->sprites.unit.loaded);
3652 if(punit->activity!=ACTIVITY_IDLE) {
3653 struct sprite *s = NULL;
3654 switch(punit->activity) {
3655 case ACTIVITY_MINE:
3656 s = t->sprites.unit.mine;
3657 break;
3658 case ACTIVITY_POLLUTION:
3659 s = t->sprites.unit.pollution;
3660 break;
3661 case ACTIVITY_FALLOUT:
3662 s = t->sprites.unit.fallout;
3663 break;
3664 case ACTIVITY_PILLAGE:
3665 s = t->sprites.unit.pillage;
3666 break;
3667 case ACTIVITY_IRRIGATE:
3668 s = t->sprites.unit.irrigate;
3669 break;
3670 case ACTIVITY_EXPLORE:
3671 s = t->sprites.unit.auto_explore;
3672 break;
3673 case ACTIVITY_FORTIFIED:
3674 s = t->sprites.unit.fortified;
3675 break;
3676 case ACTIVITY_FORTIFYING:
3677 s = t->sprites.unit.fortifying;
3678 break;
3679 case ACTIVITY_SENTRY:
3680 s = t->sprites.unit.sentry;
3681 break;
3682 case ACTIVITY_GOTO:
3683 s = t->sprites.unit.go_to;
3684 break;
3685 case ACTIVITY_TRANSFORM:
3686 s = t->sprites.unit.transform;
3687 break;
3688 case ACTIVITY_BASE:
3689 s = t->sprites.bases[punit->activity_target.obj.base].activity;
3690 break;
3691 case ACTIVITY_GEN_ROAD:
3692 s = t->sprites.roads[punit->activity_target.obj.road].activity;
3693 break;
3694 case ACTIVITY_CONVERT:
3695 s = t->sprites.unit.convert;
3696 break;
3697 default:
3698 break;
3701 ADD_SPRITE_FULL(s);
3704 if (punit->ai_controlled && punit->activity != ACTIVITY_EXPLORE) {
3705 if (is_military_unit(punit)) {
3706 ADD_SPRITE_FULL(t->sprites.unit.auto_attack);
3707 } else {
3708 ADD_SPRITE_FULL(t->sprites.unit.auto_settler);
3712 if (unit_has_orders(punit)) {
3713 if (punit->orders.repeat) {
3714 ADD_SPRITE_FULL(t->sprites.unit.patrol);
3715 } else if (punit->activity != ACTIVITY_IDLE) {
3716 ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
3717 } else {
3718 ADD_SPRITE_FULL(t->sprites.unit.go_to);
3722 if (punit->battlegroup != BATTLEGROUP_NONE) {
3723 ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
3726 if (t->sprites.unit.lowfuel
3727 && utype_fuel(ptype)
3728 && punit->fuel == 1
3729 && punit->moves_left <= 2 * SINGLE_MOVE) {
3730 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
3731 ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
3733 if (t->sprites.unit.tired
3734 && punit->moves_left < SINGLE_MOVE
3735 && ptype->move_rate > 0) {
3736 /* Show a "tired" graphic if the unit has fewer than one move
3737 * remaining, except for units for which it's full movement. */
3738 ADD_SPRITE_FULL(t->sprites.unit.tired);
3741 if (stack || punit->client.occupied) {
3742 ADD_SPRITE_FULL(t->sprites.unit.stack);
3745 if (t->sprites.unit.vet_lev[punit->veteran]) {
3746 ADD_SPRITE_FULL(t->sprites.unit.vet_lev[punit->veteran]);
3749 ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
3750 ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
3751 ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
3753 return sprs - save_sprs;
3756 /**************************************************************************
3757 Add any corner road sprites to the sprite array.
3758 **************************************************************************/
3759 static int fill_road_corner_sprites(const struct tileset *t,
3760 const struct road_type *proad,
3761 struct drawn_sprite *sprs,
3762 bool road, bool *road_near,
3763 bool hider, bool *hider_near)
3765 struct drawn_sprite *saved_sprs = sprs;
3766 int i;
3767 int road_idx = road_index(proad);
3769 if (is_cardinal_only_road(proad)) {
3770 return 0;
3773 fc_assert_ret_val(draw_roads_rails, 0);
3775 /* Roads going diagonally adjacent to this tile need to be
3776 * partly drawn on this tile. */
3778 /* Draw the corner sprite if:
3779 * - There is a diagonal road (not rail!) between two adjacent tiles.
3780 * - There is no diagonal road (not rail!) that intersects this road.
3781 * The logic is simple: roads are drawn underneath railrods, but are
3782 * not always covered by them (even in the corners!). But if a railroad
3783 * connects two tiles, only the railroad (no road) is drawn between
3784 * those tiles.
3786 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3787 enum direction8 dir = t->valid_tileset_dirs[i];
3789 if (!is_cardinal_tileset_dir(t, dir)) {
3790 /* Draw corner sprites for this non-cardinal direction. */
3791 int cw = (i + 1) % t->num_valid_tileset_dirs;
3792 int ccw
3793 = (i + t->num_valid_tileset_dirs - 1) % t->num_valid_tileset_dirs;
3794 enum direction8 dir_cw = t->valid_tileset_dirs[cw];
3795 enum direction8 dir_ccw = t->valid_tileset_dirs[ccw];
3797 if (t->sprites.roads[road_idx].corner[dir]
3798 && (road_near[dir_cw] && road_near[dir_ccw]
3799 && !(hider_near[dir_cw] && hider_near[dir_ccw]))
3800 && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
3801 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].corner[dir]);
3806 return sprs - saved_sprs;
3809 /**************************************************************************
3810 Fill all road and rail sprites into the sprite array.
3811 **************************************************************************/
3812 static int fill_road_sprite_array(const struct tileset *t,
3813 const struct road_type *proad,
3814 struct drawn_sprite *sprs,
3815 bv_roads troad,
3816 bv_roads *troad_near,
3817 struct terrain *tterrain_near[8],
3818 const struct city *pcity)
3820 struct drawn_sprite *saved_sprs = sprs;
3821 bool road, road_near[8], hider, hider_near[8];
3822 bool land_near[8], hland_near[8];
3823 bool draw_road[8], draw_single_road;
3824 enum direction8 dir;
3825 int road_idx = -1;
3826 bool cl = FALSE;
3827 enum roadstyle_id roadstyle;
3829 if (!draw_roads_rails) {
3830 /* Don't draw anything. */
3831 return 0;
3834 road_idx = road_index(proad);
3836 roadstyle = t->sprites.roads[road_idx].roadstyle;
3838 if (roadstyle == RSTYLE_RIVER) {
3839 return 0;
3842 if (road_has_flag(proad, RF_CONNECT_LAND)) {
3843 cl = TRUE;
3844 } else {
3845 int i;
3847 for (i = 0; i < 8; i++) {
3848 land_near[i] = FALSE;
3852 /* Fill some data arrays. rail_near and road_near store whether road/rail
3853 * is present in the given direction. draw_rail and draw_road store
3854 * whether road/rail is to be drawn in that direction. draw_single_road
3855 * and draw_single_rail store whether we need an isolated road/rail to be
3856 * drawn. */
3857 road = BV_ISSET(troad, road_idx);
3859 hider = FALSE;
3860 road_type_list_iterate(proad->hiders, phider) {
3861 if (BV_ISSET(troad, road_index(phider))) {
3862 hider = TRUE;
3863 break;
3865 } road_type_list_iterate_end;
3867 if (road && (!pcity || !draw_cities) && !hider) {
3868 draw_single_road = TRUE;
3869 } else {
3870 draw_single_road = FALSE;
3873 for (dir = 0; dir < 8; dir++) {
3874 bool roads_exist;
3876 /* Check if there is adjacent road/rail. */
3877 if (!is_cardinal_only_road(proad)
3878 || is_cardinal_tileset_dir(t, dir)) {
3879 road_near[dir] = BV_ISSET(troad_near[dir], road_idx);
3880 if (cl) {
3881 land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
3882 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN);
3884 } else {
3885 road_near[dir] = FALSE;
3886 land_near[dir] = FALSE;
3889 /* Draw rail/road if there is a connection from this tile to the
3890 * adjacent tile. But don't draw road if there is also a rail
3891 * connection. */
3892 roads_exist = road && (road_near[dir] || land_near[dir]);
3893 draw_road[dir] = roads_exist;
3894 hider_near[dir] = FALSE;
3895 hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
3896 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN;
3897 road_type_list_iterate(proad->hiders, phider) {
3898 bool hider_dir = FALSE;
3899 bool land_dir = FALSE;
3901 if (!is_cardinal_only_road(phider)
3902 || is_cardinal_tileset_dir(t, dir)) {
3903 if (BV_ISSET(troad_near[dir], road_index(phider))) {
3904 hider_near[dir] = TRUE;
3905 hider_dir = TRUE;
3907 if (hland_near[dir]
3908 && road_has_flag(phider, RF_CONNECT_LAND)) {
3909 land_dir = TRUE;
3911 if (hider_dir || land_dir) {
3912 if (BV_ISSET(troad, road_index(phider))) {
3913 draw_road[dir] = FALSE;
3917 } road_type_list_iterate_end;
3919 /* Don't draw an isolated road/rail if there's any connection.
3920 * draw_single_road would be true in the first place only if start tile has road,
3921 * so it will have road connection with any adjacent road tile. We check from real
3922 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
3923 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
3924 * draw single road in that case either. */
3925 if (draw_single_road && road_near[dir]) {
3926 draw_single_road = FALSE;
3930 /* Draw road corners */
3931 sprs
3932 += fill_road_corner_sprites(t, proad, sprs, road, road_near, hider, hider_near);
3934 if (roadstyle == RSTYLE_ALL_SEPARATE) {
3935 /* With RSTYLE_ALL_SEPARATE, we simply draw one road for every connection.
3936 * This means we only need a few sprites, but a lot of drawing is
3937 * necessary and it generally doesn't look very good. */
3938 int i;
3940 /* First draw roads under rails. */
3941 if (road) {
3942 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3943 if (draw_road[t->valid_tileset_dirs[i]]) {
3944 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].u.dir[i]);
3948 } else if (roadstyle == RSTYLE_PARITY_COMBINED) {
3949 /* With RSTYLE_PARITY_COMBINED, we draw one sprite for cardinal road connections,
3950 * one sprite for diagonal road connections, and the same for rail.
3951 * This means we need about 4x more sprites than in style 0, but up to
3952 * 4x less drawing is needed. The drawing quality may also be
3953 * improved. */
3955 /* First draw roads under rails. */
3956 if (road) {
3957 int road_even_tileno = 0, road_odd_tileno = 0, i;
3959 for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
3960 enum direction8 even = t->valid_tileset_dirs[2 * i];
3961 enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
3963 if (draw_road[even]) {
3964 road_even_tileno |= 1 << i;
3966 if (draw_road[odd]) {
3967 road_odd_tileno |= 1 << i;
3971 /* Draw the cardinal/even roads first. */
3972 if (road_even_tileno != 0) {
3973 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].u.combo.even[road_even_tileno]);
3975 if (road_odd_tileno != 0) {
3976 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].u.combo.odd[road_odd_tileno]);
3979 } else if (roadstyle == RSTYLE_ALL_COMBINED) {
3980 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
3981 * entire finished tiles, with a bitwise index of the presence of
3982 * roads in each direction. */
3984 /* Draw roads first */
3985 if (road) {
3986 int road_tileno = 0, i;
3988 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3989 enum direction8 dir = t->valid_tileset_dirs[i];
3991 if (draw_road[dir]) {
3992 road_tileno |= 1 << i;
3996 if (road_tileno != 0 || draw_single_road) {
3997 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].u.total[road_tileno]);
4000 } else {
4001 fc_assert(FALSE);
4004 /* Draw isolated rail/road separately (RSTYLE_ALL_SEPARATE and
4005 RSTYLE_PARITY_COMBINED only). */
4006 if (roadstyle == RSTYLE_ALL_SEPARATE || roadstyle == RSTYLE_PARITY_COMBINED) {
4007 if (draw_single_road) {
4008 ADD_SPRITE_SIMPLE(t->sprites.roads[road_idx].isolated);
4012 return sprs - saved_sprs;
4015 /**************************************************************************
4016 Return the index of the sprite to be used for irrigation or farmland in
4017 this tile.
4019 We assume that the current tile has farmland or irrigation. We then
4020 choose a sprite (index) based upon which cardinally adjacent tiles have
4021 either farmland or irrigation (the two are considered interchangable for
4022 this).
4023 **************************************************************************/
4024 static int get_irrigation_index(const struct tileset *t,
4025 bv_special *tspecial_near)
4027 int tileno = 0, i;
4029 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4030 enum direction8 dir = t->cardinal_tileset_dirs[i];
4032 /* A tile with S_FARMLAND will also have S_IRRIGATION set. */
4033 if (contains_special(tspecial_near[dir], S_IRRIGATION)) {
4034 tileno |= 1 << i;
4038 return tileno;
4041 /**************************************************************************
4042 Fill in the farmland/irrigation sprite for the tile.
4043 **************************************************************************/
4044 static int fill_irrigation_sprite_array(const struct tileset *t,
4045 struct drawn_sprite *sprs,
4046 bv_special tspecial,
4047 bv_special *tspecial_near,
4048 const struct city *pcity)
4050 struct drawn_sprite *saved_sprs = sprs;
4052 /* Tiles with S_FARMLAND also have S_IRRIGATION set. */
4053 fc_assert_ret_val(!contains_special(tspecial, S_FARMLAND)
4054 || contains_special(tspecial, S_IRRIGATION), 0);
4056 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4057 * anyway, and ends up looking bad). */
4058 if (draw_irrigation
4059 && contains_special(tspecial, S_IRRIGATION)
4060 && !(pcity && draw_cities)) {
4061 int index = get_irrigation_index(t, tspecial_near);
4063 if (contains_special(tspecial, S_FARMLAND)) {
4064 ADD_SPRITE_SIMPLE(t->sprites.tx.farmland[index]);
4065 } else {
4066 ADD_SPRITE_SIMPLE(t->sprites.tx.irrigation[index]);
4070 return sprs - saved_sprs;
4073 /**************************************************************************
4074 Fill in the city overlays for the tile. This includes the citymap
4075 overlays on the mapview as well as the tile output sprites.
4076 **************************************************************************/
4077 static int fill_city_overlays_sprite_array(const struct tileset *t,
4078 struct drawn_sprite *sprs,
4079 const struct tile *ptile,
4080 const struct city *citymode)
4082 const struct city *pcity;
4083 const struct city *pwork;
4084 struct unit *psettler;
4085 struct drawn_sprite *saved_sprs = sprs;
4086 int city_x, city_y;
4087 const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
4089 if (NULL == ptile || TILE_UNKNOWN == client_tile_get_known(ptile)) {
4090 return 0;
4092 pwork = tile_worked(ptile);
4094 if (citymode) {
4095 pcity = citymode;
4096 } else {
4097 pcity = find_city_or_settler_near_tile(ptile, &psettler);
4100 /* Below code does not work if pcity is invisible.
4101 * Make sure it is not. */
4102 fc_assert_ret_val(pcity == NULL || pcity->tile != NULL, 0);
4103 if (pcity && !pcity->tile) {
4104 pcity = NULL;
4107 if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
4108 /* FIXME: check elsewhere for valid tile (instead of above) */
4110 if (!citymode && pcity->client.colored) {
4111 /* Add citymap overlay for a city. */
4112 int index = pcity->client.color_index % NUM_CITY_COLORS;
4114 if (NULL != pwork && pwork == pcity) {
4115 ADD_SPRITE_SIMPLE(t->sprites.city.worked_tile_overlay.p[index]);
4116 } else if (city_can_work_tile(pcity, ptile)) {
4117 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[index]);
4119 } else if (NULL != pwork && pwork == pcity
4120 && (citymode || draw_city_output)) {
4121 /* Add on the tile output sprites. */
4122 int food = city_tile_output_now(pcity, ptile, O_FOOD);
4123 int shields = city_tile_output_now(pcity, ptile, O_SHIELD);
4124 int trade = city_tile_output_now(pcity, ptile, O_TRADE);
4125 const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
4126 const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
4128 food = CLIP(0, food, NUM_TILES_DIGITS - 1);
4129 shields = CLIP(0, shields, NUM_TILES_DIGITS - 1);
4130 trade = CLIP(0, trade, NUM_TILES_DIGITS - 1);
4132 ADD_SPRITE(t->sprites.city.tile_foodnum[food], TRUE, ox, oy);
4133 ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
4134 ADD_SPRITE(t->sprites.city.tile_tradenum[trade], TRUE, ox, oy);
4136 } else if (psettler && psettler->client.colored) {
4137 /* Add citymap overlay for a unit. */
4138 int index = psettler->client.color_index % NUM_CITY_COLORS;
4140 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[index]);
4143 return sprs - saved_sprs;
4146 /****************************************************************************
4147 Helper function for fill_terrain_sprite_layer.
4148 Fill in the sprite array for blended terrain.
4149 ****************************************************************************/
4150 static int fill_terrain_sprite_blending(const struct tileset *t,
4151 struct drawn_sprite *sprs,
4152 const struct tile *ptile,
4153 const struct terrain *pterrain,
4154 struct terrain **tterrain_near)
4156 struct drawn_sprite *saved_sprs = sprs;
4157 const int W = t->normal_tile_width, H = t->normal_tile_height;
4158 const int offsets[4][2] = {
4159 {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4161 enum direction4 dir = 0;
4164 * We want to mark unknown tiles so that an unreal tile will be
4165 * given the same marking as our current tile - that way we won't
4166 * get the "unknown" dither along the edge of the map.
4168 for (; dir < 4; dir++) {
4169 struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
4170 struct terrain *other;
4172 if (!tile1
4173 || client_tile_get_known(tile1) == TILE_UNKNOWN
4174 || pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
4175 || (0 == t->sprites.drawing[terrain_index(other)]->blending
4176 && NULL == t->sprites.drawing[terrain_index(other)]->blender)) {
4177 continue;
4180 ADD_SPRITE(t->sprites.drawing[terrain_index(other)]->blend[dir], TRUE,
4181 offsets[dir][0], offsets[dir][1]);
4184 return sprs - saved_sprs;
4187 /****************************************************************************
4188 Add sprites for fog (and some forms of darkness).
4189 ****************************************************************************/
4190 static int fill_fog_sprite_array(const struct tileset *t,
4191 struct drawn_sprite *sprs,
4192 const struct tile *ptile,
4193 const struct tile_edge *pedge,
4194 const struct tile_corner *pcorner)
4196 struct drawn_sprite *saved_sprs = sprs;
4198 if (t->fogstyle == FOG_SPRITE && draw_fog_of_war
4199 && NULL != ptile
4200 && TILE_KNOWN_UNSEEN == client_tile_get_known(ptile)) {
4201 /* With FOG_AUTO, fog is done this way. */
4202 ADD_SPRITE_SIMPLE(t->sprites.tx.fog);
4205 if (t->darkness_style == DARKNESS_CORNER && pcorner && draw_fog_of_war) {
4206 int i, tileno = 0;
4208 for (i = 3; i >= 0; i--) {
4209 const int unknown = 0, fogged = 1, known = 2;
4210 int value = -1;
4212 if (!pcorner->tile[i]) {
4213 value = fogged;
4214 } else {
4215 switch (client_tile_get_known(pcorner->tile[i])) {
4216 case TILE_KNOWN_SEEN:
4217 value = known;
4218 break;
4219 case TILE_KNOWN_UNSEEN:
4220 value = fogged;
4221 break;
4222 case TILE_UNKNOWN:
4223 value = unknown;
4224 break;
4227 fc_assert(value >= 0 && value < 3);
4229 tileno = tileno * 3 + value;
4232 if (t->sprites.tx.fullfog[tileno]) {
4233 ADD_SPRITE_SIMPLE(t->sprites.tx.fullfog[tileno]);
4237 return sprs - saved_sprs;
4240 /****************************************************************************
4241 Helper function for fill_terrain_sprite_layer.
4242 ****************************************************************************/
4243 static int fill_terrain_sprite_array(struct tileset *t,
4244 struct drawn_sprite *sprs,
4245 int l, /* layer_num */
4246 const struct tile *ptile,
4247 const struct terrain *pterrain,
4248 struct terrain **tterrain_near,
4249 struct drawing_data *draw)
4251 struct drawn_sprite *saved_sprs = sprs;
4252 struct drawing_layer *dlp = &draw->layer[l];
4253 int this = dlp->match_index[0];
4254 int that = dlp->match_index[1];
4255 int ox = dlp->offset_x;
4256 int oy = dlp->offset_y;
4257 int i;
4259 #define MATCH(dir) \
4260 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4261 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4262 : -1)
4264 switch (dlp->sprite_type) {
4265 case CELL_WHOLE:
4267 switch (dlp->match_style) {
4268 case MATCH_NONE:
4270 int count = sprite_vector_size(&dlp->base);
4272 if (count > 0) {
4273 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4274 * to limit the number to a handleable size [0..32000). */
4275 count = fc_randomly(tile_index(ptile) % 32000, count);
4277 if (dlp->is_tall) {
4278 ox += FULL_TILE_X_OFFSET;
4279 oy += FULL_TILE_Y_OFFSET;
4281 ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
4283 break;
4285 case MATCH_SAME:
4287 int tileno = 0;
4289 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4290 enum direction8 dir = t->cardinal_tileset_dirs[i];
4292 if (MATCH(dir) == this) {
4293 tileno |= 1 << i;
4297 if (dlp->is_tall) {
4298 ox += FULL_TILE_X_OFFSET;
4299 oy += FULL_TILE_Y_OFFSET;
4301 ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
4302 break;
4304 case MATCH_PAIR:
4305 case MATCH_FULL:
4306 fc_assert(FALSE); /* not yet defined */
4307 break;
4309 break;
4311 case CELL_CORNER:
4313 /* Divide the tile up into four rectangular cells. Each of these
4314 * cells covers one corner, and each is adjacent to 3 different
4315 * tiles. For each cell we pick a sprite based upon the adjacent
4316 * terrains at each of those tiles. Thus, we have 8 different sprites
4317 * for each of the 4 cells (32 sprites total).
4319 * These arrays correspond to the direction4 ordering. */
4320 const int W = t->normal_tile_width;
4321 const int H = t->normal_tile_height;
4322 const int iso_offsets[4][2] = {
4323 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
4325 const int noniso_offsets[4][2] = {
4326 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
4329 /* put corner cells */
4330 for (i = 0; i < NUM_CORNER_DIRS; i++) {
4331 const int count = dlp->match_indices;
4332 int array_index = 0;
4333 enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
4334 int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
4335 int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
4336 int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
4337 struct sprite *s;
4339 /* synthesize 4 dimensional array? */
4340 switch (dlp->match_style) {
4341 case MATCH_NONE:
4342 /* We have no need for matching, just plug the piece in place. */
4343 break;
4344 case MATCH_SAME:
4345 array_index = array_index * 2 + (m[2] != this);
4346 array_index = array_index * 2 + (m[1] != this);
4347 array_index = array_index * 2 + (m[0] != this);
4348 break;
4349 case MATCH_PAIR:
4350 array_index = array_index * 2 + (m[2] == that);
4351 array_index = array_index * 2 + (m[1] == that);
4352 array_index = array_index * 2 + (m[0] == that);
4353 break;
4354 case MATCH_FULL:
4355 default:
4357 int n[3];
4358 int j = 0;
4359 for (; j < 3; j++) {
4360 int k = 0;
4361 for (; k < count; k++) {
4362 n[j] = k; /* default to last entry */
4363 if (m[j] == dlp->match_index[k])
4365 break;
4369 array_index = array_index * count + n[2];
4370 array_index = array_index * count + n[1];
4371 array_index = array_index * count + n[0];
4373 break;
4375 array_index = array_index * NUM_CORNER_DIRS + i;
4377 s = dlp->cells[array_index];
4378 if (s) {
4379 ADD_SPRITE(s, TRUE, x, y);
4382 break;
4385 #undef MATCH
4387 return sprs - saved_sprs;
4390 /****************************************************************************
4391 Helper function for fill_terrain_sprite_layer.
4392 Fill in the sprite array of darkness.
4393 ****************************************************************************/
4394 static int fill_terrain_sprite_darkness(struct tileset *t,
4395 struct drawn_sprite *sprs,
4396 const struct tile *ptile,
4397 struct terrain **tterrain_near)
4399 struct drawn_sprite *saved_sprs = sprs;
4400 int i, tileno;
4401 struct tile *adjc_tile;
4403 #define UNKNOWN(dir) \
4404 ((adjc_tile = mapstep(ptile, (dir))) \
4405 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4407 switch (t->darkness_style) {
4408 case DARKNESS_NONE:
4409 break;
4410 case DARKNESS_ISORECT:
4411 for (i = 0; i < 4; i++) {
4412 const int W = t->normal_tile_width, H = t->normal_tile_height;
4413 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
4415 if (UNKNOWN(DIR4_TO_DIR8[i])) {
4416 ADD_SPRITE(t->sprites.tx.darkness[i], TRUE,
4417 offsets[i][0], offsets[i][1]);
4420 break;
4421 case DARKNESS_CARD_SINGLE:
4422 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4423 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4424 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[i]);
4427 break;
4428 case DARKNESS_CARD_FULL:
4429 /* We're looking to find the INDEX_NSEW for the directions that
4430 * are unknown. We want to mark unknown tiles so that an unreal
4431 * tile will be given the same marking as our current tile - that
4432 * way we won't get the "unknown" dither along the edge of the
4433 * map. */
4434 tileno = 0;
4435 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4436 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4437 tileno |= 1 << i;
4441 if (tileno != 0) {
4442 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[tileno]);
4444 break;
4445 case DARKNESS_CORNER:
4446 /* Handled separately. */
4447 break;
4449 #undef UNKNOWN
4451 return sprs - saved_sprs;
4454 /****************************************************************************
4455 Add sprites for the base tile to the sprite list. This doesn't
4456 include specials or rivers.
4457 ****************************************************************************/
4458 static int fill_terrain_sprite_layer(struct tileset *t,
4459 struct drawn_sprite *sprs,
4460 int layer_num,
4461 const struct tile *ptile,
4462 const struct terrain *pterrain,
4463 struct terrain **tterrain_near)
4465 struct sprite *sprite;
4466 struct drawn_sprite *saved_sprs = sprs;
4467 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
4468 const int l = (draw->is_reversed
4469 ? (draw->num_layers - layer_num - 1) : layer_num);
4471 fc_assert(layer_num < TERRAIN_LAYER_COUNT);
4473 /* Skip the normal drawing process. */
4474 /* FIXME: this should avoid calling load_sprite since it's slow and
4475 * increases the refcount without limit. */
4476 if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite))) {
4477 if (l == 0) {
4478 ADD_SPRITE_SIMPLE(sprite);
4479 return 1;
4480 } else {
4481 return 0;
4485 if (l < draw->num_layers) {
4486 sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
4488 if ((l + 1) == draw->blending) {
4489 sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
4493 /* Add darkness on top of the designed terrain layer. Note that darkness is always
4494 * drawn, even in citymode, etc. */
4495 if (layer_num == t->darkness_layer) {
4496 sprs += fill_terrain_sprite_darkness(t, sprs, ptile, tterrain_near);
4499 return sprs - saved_sprs;
4502 /****************************************************************************
4503 Indicate whether a unit is to be drawn with a surrounding city outline
4504 under current conditions.
4505 (This includes being in focus, but if the caller has already checked that,
4506 they can bypass this slightly expensive check with check_focus == FALSE.)
4507 ****************************************************************************/
4508 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
4510 /* Display an outline for city-builder type units if they are selected,
4511 * and on a tile where a city can be built.
4512 * But suppress the outline if the unit has orders (likely it is in
4513 * transit to somewhere else and this will just slow down redraws). */
4514 return draw_city_outlines
4515 && unit_has_type_flag(punit, UTYF_CITIES)
4516 && !unit_has_orders(punit)
4517 && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN
4518 && city_can_be_built_here(unit_tile(punit), punit))
4519 && (!check_focus || unit_is_in_focus(punit));
4522 /****************************************************************************
4523 Fill in the grid sprites for the given tile, city, and unit.
4524 ****************************************************************************/
4525 static int fill_grid_sprite_array(const struct tileset *t,
4526 struct drawn_sprite *sprs,
4527 const struct tile *ptile,
4528 const struct tile_edge *pedge,
4529 const struct tile_corner *pcorner,
4530 const struct unit *punit,
4531 const struct city *pcity,
4532 const struct city *citymode)
4534 struct drawn_sprite *saved_sprs = sprs;
4536 if (pedge) {
4537 bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
4538 bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
4539 int i;
4540 struct unit_list *pfocus_units = get_units_in_focus();
4542 for (i = 0; i < NUM_EDGE_TILES; i++) {
4543 int dummy_x, dummy_y;
4544 const struct tile *tile = pedge->tile[i];
4545 struct player *powner = tile ? tile_owner(tile) : NULL;
4547 known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
4548 unit[i] = FALSE;
4549 if (tile && !citymode) {
4550 unit_list_iterate(pfocus_units, pfocus_unit) {
4551 if (unit_drawn_with_city_outline(pfocus_unit, FALSE)
4552 && city_tile_to_city_map(&dummy_x, &dummy_y,
4553 game.info.init_city_radius_sq,
4554 unit_tile(pfocus_unit), tile)) {
4555 unit[i] = TRUE;
4556 break;
4558 } unit_list_iterate_end;
4560 worked[i] = FALSE;
4562 city[i] = (tile
4563 && (NULL == powner || NULL == client.conn.playing
4564 || powner == client.conn.playing)
4565 && (NULL == client.conn.playing
4566 || player_in_city_map(client.conn.playing, tile)));
4567 if (city[i]) {
4568 if (citymode) {
4569 /* In citymode, we only draw worked tiles for this city - other
4570 * tiles may be marked as unavailable. */
4571 worked[i] = (tile_worked(tile) == citymode);
4572 } else {
4573 worked[i] = (NULL != tile_worked(tile));
4578 if (mapdeco_is_highlight_set(pedge->tile[0])
4579 || mapdeco_is_highlight_set(pedge->tile[1])) {
4580 ADD_SPRITE_SIMPLE(t->sprites.grid.selected[pedge->type]);
4581 } else if (!draw_terrain && draw_coastline
4582 && pedge->tile[0] && pedge->tile[1]
4583 && known[0] && known[1]
4584 && (is_ocean_tile(pedge->tile[0])
4585 ^ is_ocean_tile(pedge->tile[1]))) {
4586 ADD_SPRITE_SIMPLE(t->sprites.grid.coastline[pedge->type]);
4587 } else if (draw_map_grid) {
4588 if (worked[0] || worked[1]) {
4589 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
4590 } else if (city[0] || city[1]) {
4591 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
4592 } else if (known[0] || known[1]) {
4593 ADD_SPRITE_SIMPLE(t->sprites.grid.main[pedge->type]);
4595 } else if (draw_city_outlines) {
4596 if (XOR(city[0], city[1])) {
4597 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
4599 if (XOR(unit[0], unit[1])) {
4600 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
4604 if (draw_borders
4605 && BORDERS_DISABLED != game.info.borders
4606 && known[0]
4607 && known[1]) {
4608 struct player *owner0 = tile_owner(pedge->tile[0]);
4609 struct player *owner1 = tile_owner(pedge->tile[1]);
4611 if (owner0 != owner1) {
4612 if (owner0) {
4613 int plrid = player_index(owner0);
4614 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
4615 [pedge->type][0]);
4617 if (owner1) {
4618 int plrid = player_index(owner1);
4619 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
4620 [pedge->type][1]);
4624 } else if (NULL != ptile && TILE_UNKNOWN != client_tile_get_known(ptile)) {
4625 int cx, cy;
4627 if (citymode
4628 /* test to ensure valid coordinates? */
4629 && city_base_to_city_map(&cx, &cy, citymode, ptile)
4630 && !client_city_can_work_tile(citymode, ptile)) {
4631 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
4634 if (draw_native && citymode == NULL) {
4635 bool native = TRUE;
4636 struct unit_list *pfocus_units = get_units_in_focus();
4638 unit_list_iterate(pfocus_units, punit) {
4639 if (!is_native_tile(unit_type(punit), ptile)) {
4640 native = FALSE;
4641 break;
4643 } unit_list_iterate_end;
4645 if (!native) {
4646 if (t->sprites.grid.nonnative != NULL) {
4647 ADD_SPRITE_SIMPLE(t->sprites.grid.nonnative);
4648 } else {
4649 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
4655 return sprs - saved_sprs;
4658 /****************************************************************************
4659 Fill in the given sprite array with any needed goto sprites.
4660 ****************************************************************************/
4661 static int fill_goto_sprite_array(const struct tileset *t,
4662 struct drawn_sprite *sprs,
4663 const struct tile *ptile,
4664 const struct tile_edge *pedge,
4665 const struct tile_corner *pcorner)
4667 struct drawn_sprite *saved_sprs = sprs;
4669 if (is_valid_goto_destination(ptile)) {
4670 bool warn= FALSE;
4671 int length;
4673 goto_get_turns(NULL, &length);
4675 if (0 > length) {
4676 ADD_SPRITE_SIMPLE(t->sprites.path.turns[0]);
4677 warn = TRUE;
4678 } else {
4679 ADD_SPRITE_SIMPLE(t->sprites.path.turns[length % 10]);
4680 if (10 <= length) {
4681 ADD_SPRITE_SIMPLE(t->sprites.path.turns_tens[(length / 10) % 10]);
4682 if (100 <= length) {
4683 struct sprite *sprite =
4684 t->sprites.path.turns_hundreds[(length / 100) % 10];
4686 if (NULL != sprite) {
4687 ADD_SPRITE_SIMPLE(sprite);
4688 } else {
4689 warn = TRUE;
4691 if (1000 <= length) {
4692 warn = TRUE;
4698 if (warn) {
4699 /* Warn only once by tileset. */
4700 static char last_reported[256] = "";
4702 if (0 != strcmp(last_reported, t->name)) {
4703 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
4704 "such as %d. Path not displayed as expected."),
4705 t->name, length);
4706 sz_strlcpy(last_reported, t->name);
4711 return sprs - saved_sprs;
4714 /****************************************************************************
4715 Fill in the sprite array for the given tile, city, and unit.
4717 ptile, if specified, gives the tile. If specified the terrain and specials
4718 will be drawn for this tile. In this case (map_x,map_y) should give the
4719 location of the tile.
4721 punit, if specified, gives the unit. For tile drawing this should
4722 generally be get_drawable_unit(); otherwise it can be any unit.
4724 pcity, if specified, gives the city. For tile drawing this should
4725 generally be tile_city(ptile); otherwise it can be any city.
4727 citymode specifies whether this is part of a citydlg. If so some drawing
4728 is done differently.
4729 ****************************************************************************/
4730 int fill_sprite_array(struct tileset *t,
4731 struct drawn_sprite *sprs, enum mapview_layer layer,
4732 const struct tile *ptile,
4733 const struct tile_edge *pedge,
4734 const struct tile_corner *pcorner,
4735 const struct unit *punit, const struct city *pcity,
4736 const struct city *citymode,
4737 const struct unit_type *putype)
4739 int tileno, dir;
4740 bv_special tspecial_near[8];
4741 bv_special tspecial;
4742 bv_roads troad;
4743 bv_roads troad_near[8];
4744 struct terrain *tterrain_near[8];
4745 struct terrain *pterrain = NULL;
4746 struct drawn_sprite *save_sprs = sprs;
4747 struct player *owner = NULL;
4748 /* Unit drawing is disabled when the view options are turned off,
4749 * but only where we're drawing on the mapview. */
4750 bool do_draw_unit = (punit && (draw_units || !ptile
4751 || (draw_focus_unit
4752 && unit_is_in_focus(punit))));
4753 bool solid_bg = (solid_color_behind_units
4754 && (do_draw_unit
4755 || (pcity && draw_cities)
4756 || (ptile && !draw_terrain)));
4758 if (citymode) {
4759 int count = 0, i, cx, cy;
4760 const struct tile *const *tiles = NULL;
4761 bool valid = FALSE;
4763 if (ptile) {
4764 tiles = &ptile;
4765 count = 1;
4766 } else if (pcorner) {
4767 tiles = pcorner->tile;
4768 count = NUM_CORNER_TILES;
4769 } else if (pedge) {
4770 tiles = pedge->tile;
4771 count = NUM_EDGE_TILES;
4774 for (i = 0; i < count; i++) {
4775 if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
4776 valid = TRUE;
4777 break;
4780 if (!valid) {
4781 return 0;
4785 if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
4786 tspecial = tile_specials(ptile);
4787 troad = tile_roads(ptile);
4788 pterrain = tile_terrain(ptile);
4790 if (NULL != pterrain) {
4791 build_tile_data(ptile, pterrain, tterrain_near, tspecial_near,
4792 troad_near);
4793 } else {
4794 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
4795 TILE_XY(ptile));
4797 } else {
4798 BV_CLR_ALL(tspecial);
4799 BV_CLR_ALL(troad);
4802 switch (layer) {
4803 case LAYER_BACKGROUND:
4804 /* Set up background color. */
4805 if (solid_color_behind_units) {
4806 if (do_draw_unit) {
4807 owner = unit_owner(punit);
4808 } else if (pcity && draw_cities) {
4809 owner = city_owner(pcity);
4812 if (owner) {
4813 ADD_SPRITE_SIMPLE(t->sprites.player[player_index(owner)].background);
4814 } else if (ptile && !draw_terrain) {
4815 ADD_SPRITE_SIMPLE(t->sprites.background.graphic);
4817 break;
4819 case LAYER_TERRAIN1:
4820 if (NULL != pterrain && draw_terrain && !solid_bg) {
4821 sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
4823 break;
4825 case LAYER_TERRAIN2:
4826 if (NULL != pterrain && draw_terrain && !solid_bg) {
4827 sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
4829 break;
4831 case LAYER_TERRAIN3:
4832 if (NULL != pterrain && draw_terrain && !solid_bg) {
4833 fc_assert(MAX_NUM_LAYERS == 3);
4834 sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
4836 break;
4838 case LAYER_WATER:
4839 if (NULL != pterrain) {
4840 if (draw_terrain && !solid_bg
4841 && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
4842 for (dir = 0; dir < 4; dir++) {
4843 int didx = DIR4_TO_DIR8[dir];
4845 road_type_list_iterate(t->rivers, priver) {
4846 int idx = road_index(priver);
4848 if (BV_ISSET(troad_near[didx], idx)) {
4849 ADD_SPRITE_SIMPLE(t->sprites.roads[idx].u.rivers.outlet[dir]);
4850 break;
4852 } road_type_list_iterate_end;
4856 sprs += fill_irrigation_sprite_array(t, sprs, tspecial, tspecial_near,
4857 pcity);
4859 if (draw_terrain && !solid_bg) {
4860 road_type_list_iterate(t->rivers, priver) {
4861 int idx = road_index(priver);
4863 if (BV_ISSET(troad, idx)) {
4864 int i;
4866 /* Draw rivers on top of irrigation. */
4867 tileno = 0;
4868 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4869 enum direction8 dir = t->cardinal_tileset_dirs[i];
4871 if (terrain_type_terrain_class(tterrain_near[dir]) == TC_OCEAN
4872 || BV_ISSET(troad_near[dir], idx)) {
4873 tileno |= 1 << i;
4877 ADD_SPRITE_SIMPLE(t->sprites.roads[idx].u.rivers.spec[tileno]);
4879 } road_type_list_iterate_end;
4882 break;
4884 case LAYER_ROADS:
4885 if (NULL != pterrain) {
4886 road_type_iterate(proad) {
4887 sprs += fill_road_sprite_array(t, proad, sprs,
4888 troad, troad_near,
4889 tterrain_near, pcity);
4890 } road_type_iterate_end;
4892 break;
4894 case LAYER_SPECIAL1:
4895 if (NULL != pterrain) {
4896 if (draw_specials) {
4897 if (tile_resource_is_valid(ptile)) {
4898 ADD_SPRITE_SIMPLE(t->sprites.resource[resource_index(tile_resource(ptile))]);
4902 if (ptile && draw_fortress_airbase) {
4903 base_type_iterate(pbase) {
4904 if (tile_has_base(ptile, pbase)
4905 && t->sprites.bases[base_index(pbase)].background) {
4906 ADD_SPRITE_FULL(t->sprites.bases[base_index(pbase)].background);
4908 } base_type_iterate_end;
4911 if (draw_mines && contains_special(tspecial, S_MINE)) {
4912 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
4914 if (NULL != draw->mine) {
4915 ADD_SPRITE_SIMPLE(draw->mine);
4919 if (draw_specials && contains_special(tspecial, S_HUT)) {
4920 ADD_SPRITE_SIMPLE(t->sprites.tx.village);
4923 break;
4925 case LAYER_GRID1:
4926 if (t->type == TS_ISOMETRIC) {
4927 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
4928 punit, pcity, citymode);
4930 break;
4932 case LAYER_CITY1:
4933 /* City. Some city sprites are drawn later. */
4934 if (pcity && draw_cities) {
4935 if (!draw_full_citybar && !solid_color_behind_units) {
4936 ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
4937 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
4938 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
4940 /* For iso-view the city.wall graphics include the full city, whereas
4941 * for non-iso view they are an overlay on top of the base city
4942 * graphic. */
4943 if (t->type == TS_OVERVIEW || !pcity->client.walls) {
4944 ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.tile, pcity));
4946 if (t->type == TS_ISOMETRIC && pcity->client.walls) {
4947 ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.wall, pcity));
4949 if (!draw_full_citybar && pcity->client.occupied) {
4950 ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.occupied, pcity));
4952 if (t->type == TS_OVERVIEW && pcity->client.walls) {
4953 ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.wall, pcity));
4955 if (pcity->client.unhappy) {
4956 ADD_SPRITE_FULL(t->sprites.city.disorder);
4959 break;
4961 case LAYER_SPECIAL2:
4962 if (NULL != pterrain) {
4963 if (ptile && draw_fortress_airbase) {
4964 base_type_iterate(pbase) {
4965 if (tile_has_base(ptile, pbase)
4966 && t->sprites.bases[base_index(pbase)].middleground) {
4967 ADD_SPRITE_FULL(t->sprites.bases[base_index(pbase)].middleground);
4969 } base_type_iterate_end;
4972 if (draw_pollution && contains_special(tspecial, S_POLLUTION)) {
4973 ADD_SPRITE_SIMPLE(t->sprites.tx.pollution);
4975 if (draw_pollution && contains_special(tspecial, S_FALLOUT)) {
4976 ADD_SPRITE_SIMPLE(t->sprites.tx.fallout);
4979 break;
4981 case LAYER_UNIT:
4982 case LAYER_FOCUS_UNIT:
4983 if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
4984 bool stacked = ptile && (unit_list_size(ptile->units) > 1);
4985 bool backdrop = !pcity;
4987 if (ptile && unit_is_in_focus(punit)
4988 && t->sprites.unit.select[0]) {
4989 /* Special case for drawing the selection rectangle. The blinking
4990 * unit is handled separately, inside get_drawable_unit(). */
4991 ADD_SPRITE_SIMPLE(t->sprites.unit.select[focus_unit_state]);
4994 sprs += fill_unit_sprite_array(t, sprs, punit, stacked, backdrop);
4995 } else if (putype != NULL) {
4996 /* Only the sprite for the unit type. */
4997 sprs += fill_unit_type_sprite_array(t, sprs, putype,
4998 direction8_invalid());
5000 break;
5002 case LAYER_SPECIAL3:
5003 if (NULL != pterrain) {
5004 if (ptile && draw_fortress_airbase) {
5005 bool show_flag = FALSE;
5006 struct player *owner = base_owner(ptile);
5008 base_type_iterate(pbase) {
5009 if (tile_has_base(ptile, pbase)) {
5010 if (t->sprites.bases[base_index(pbase)].foreground) {
5011 /* Draw fortress front in iso-view (non-iso view only has a fortress
5012 * back). */
5013 ADD_SPRITE_FULL(t->sprites.bases[base_index(pbase)].foreground);
5015 if (base_has_flag(pbase, BF_SHOW_FLAG)) {
5016 show_flag = TRUE;
5019 } base_type_iterate_end;
5021 if (show_flag && owner != NULL) {
5022 ADD_SPRITE(get_nation_flag_sprite(t, nation_of_player(owner)), TRUE,
5023 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5024 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5028 break;
5030 case LAYER_FOG:
5031 sprs += fill_fog_sprite_array(t, sprs, ptile, pedge, pcorner);
5032 break;
5034 case LAYER_CITY2:
5035 /* City size. Drawing this under fog makes it hard to read. */
5036 if (pcity && draw_cities && !draw_full_citybar) {
5037 bool warn = FALSE;
5039 ADD_SPRITE(t->sprites.city.size[city_size_get(pcity) % 10],
5040 FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5041 if (10 <= city_size_get(pcity)) {
5042 ADD_SPRITE(t->sprites.city.size_tens[(city_size_get(pcity) / 10)
5043 % 10], FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5044 if (100 <= city_size_get(pcity)) {
5045 struct sprite *sprite =
5046 t->sprites.city.size_hundreds[(city_size_get(pcity) / 100) % 10];
5048 if (NULL != sprite) {
5049 ADD_SPRITE(sprite, FALSE,
5050 FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5051 } else {
5052 warn = TRUE;
5054 if (1000 <= city_size_get(pcity)) {
5055 warn = TRUE;
5060 if (warn) {
5061 /* Warn only once by tileset. */
5062 static char last_reported[256] = "";
5064 if (0 != strcmp(last_reported, t->name)) {
5065 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5066 "such as %d. Size not displayed as expected."),
5067 t->name, city_size_get(pcity));
5068 sz_strlcpy(last_reported, t->name);
5072 break;
5074 case LAYER_GRID2:
5075 if (t->type == TS_OVERVIEW) {
5076 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5077 punit, pcity, citymode);
5079 break;
5081 case LAYER_OVERLAYS:
5082 sprs += fill_city_overlays_sprite_array(t, sprs, ptile, citymode);
5083 if (mapdeco_is_crosshair_set(ptile)) {
5084 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5086 break;
5088 case LAYER_CITYBAR:
5089 case LAYER_TILELABEL:
5090 /* Nothing. This is just a placeholder. */
5091 break;
5093 case LAYER_GOTO:
5094 if (ptile && goto_is_active()) {
5095 sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
5097 break;
5099 case LAYER_EDITOR:
5100 if (ptile && editor_is_active()) {
5101 if (editor_tile_is_selected(ptile)) {
5102 int color = 2 % tileset_num_city_colors(tileset);
5103 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
5106 if (NULL != map_startpos_get(ptile)) {
5107 /* FIXME: Use a more representative sprite. */
5108 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5111 break;
5113 case LAYER_COUNT:
5114 fc_assert(FALSE);
5115 break;
5118 return sprs - save_sprs;
5121 /**********************************************************************
5122 Set city tiles sprite values; should only happen after
5123 tilespec_load_tiles().
5124 ***********************************************************************/
5125 void tileset_setup_city_tiles(struct tileset *t, int style)
5127 if (style == game.control.styles_count - 1) {
5129 /* Free old sprites */
5130 free_city_sprite(t->sprites.city.tile);
5131 free_city_sprite(t->sprites.city.wall);
5132 free_city_sprite(t->sprites.city.occupied);
5134 t->sprites.city.tile = load_city_sprite(t, "city");
5135 t->sprites.city.wall = load_city_sprite(t, "wall");
5136 t->sprites.city.occupied = load_city_sprite(t, "occupied");
5138 for (style = 0; style < game.control.styles_count; style++) {
5139 if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
5140 tileset_error(LOG_FATAL, _("City style \"%s\": no city graphics."),
5141 city_style_rule_name(style));
5143 if (t->sprites.city.wall->styles[style].land_num_thresholds == 0) {
5144 tileset_error(LOG_FATAL, _("City style \"%s\": no wall graphics."),
5145 city_style_rule_name(style));
5147 if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
5148 tileset_error(LOG_FATAL, _("City style \"%s\": no occupied graphics."),
5149 city_style_rule_name(style));
5155 /****************************************************************************
5156 Return the amount of time between calls to toggle_focus_unit_state.
5157 The main loop needs to call toggle_focus_unit_state about this often
5158 to do the active-unit animation.
5159 ****************************************************************************/
5160 double get_focus_unit_toggle_timeout(const struct tileset *t)
5162 if (t->sprites.unit.select[0]) {
5163 return 0.1;
5164 } else {
5165 return 0.5;
5169 /****************************************************************************
5170 Reset the focus unit state. This should be called when changing
5171 focus units.
5172 ****************************************************************************/
5173 void reset_focus_unit_state(struct tileset *t)
5175 focus_unit_state = 0;
5178 /****************************************************************************
5179 Setup tileset for showing combat where focus unit participates.
5180 ****************************************************************************/
5181 void focus_unit_in_combat(struct tileset *t)
5183 if (!t->sprites.unit.select[0]) {
5184 reset_focus_unit_state(t);
5188 /****************************************************************************
5189 Toggle/increment the focus unit state. This should be called once
5190 every get_focus_unit_toggle_timeout() seconds.
5191 ****************************************************************************/
5192 void toggle_focus_unit_state(struct tileset *t)
5194 focus_unit_state++;
5195 if (t->sprites.unit.select[0]) {
5196 focus_unit_state %= NUM_TILES_SELECT;
5197 } else {
5198 focus_unit_state %= 2;
5202 /**********************************************************************
5203 Find unit that we can display from given tile.
5204 ***********************************************************************/
5205 struct unit *get_drawable_unit(const struct tileset *t,
5206 struct tile *ptile,
5207 const struct city *citymode)
5209 struct unit *punit = find_visible_unit(ptile);
5211 if (!punit)
5212 return NULL;
5214 if (citymode && unit_owner(punit) == city_owner(citymode))
5215 return NULL;
5217 if (!unit_is_in_focus(punit)
5218 || t->sprites.unit.select[0] || focus_unit_state == 0)
5219 return punit;
5220 else
5221 return NULL;
5224 /****************************************************************************
5225 This patch unloads all sprites from the sprite hash (the hash itself
5226 is left intact).
5227 ****************************************************************************/
5228 static void unload_all_sprites(struct tileset *t)
5230 if (t->sprite_hash) {
5231 sprite_hash_iterate(t->sprite_hash, tag_name, ss) {
5232 while (ss->ref_count > 0) {
5233 unload_sprite(t, tag_name);
5235 } sprite_hash_iterate_end;
5239 /**********************************************************************
5240 Free all sprites from tileset.
5241 ***********************************************************************/
5242 void tileset_free_tiles(struct tileset *t)
5244 log_debug("tileset_free_tiles()");
5246 unload_all_sprites(t);
5248 free_city_sprite(t->sprites.city.tile);
5249 t->sprites.city.tile = NULL;
5250 free_city_sprite(t->sprites.city.wall);
5251 t->sprites.city.wall = NULL;
5252 free_city_sprite(t->sprites.city.occupied);
5253 t->sprites.city.occupied = NULL;
5255 if (t->sprite_hash) {
5256 sprite_hash_destroy(t->sprite_hash);
5257 t->sprite_hash = NULL;
5260 small_sprite_list_iterate(t->small_sprites, ss) {
5261 small_sprite_list_remove(t->small_sprites, ss);
5262 if (ss->file) {
5263 free(ss->file);
5265 fc_assert(ss->sprite == NULL);
5266 free(ss);
5267 } small_sprite_list_iterate_end;
5269 specfile_list_iterate(t->specfiles, sf) {
5270 specfile_list_remove(t->specfiles, sf);
5271 free(sf->file_name);
5272 if (sf->big_sprite) {
5273 free_sprite(sf->big_sprite);
5274 sf->big_sprite = NULL;
5276 free(sf);
5277 } specfile_list_iterate_end;
5279 sprite_vector_iterate(&t->sprites.city.worked_tile_overlay, psprite) {
5280 free_sprite(*psprite);
5281 } sprite_vector_iterate_end;
5282 sprite_vector_free(&t->sprites.city.worked_tile_overlay);
5284 sprite_vector_iterate(&t->sprites.city.unworked_tile_overlay, psprite) {
5285 free_sprite(*psprite);
5286 } sprite_vector_iterate_end;
5287 sprite_vector_free(&t->sprites.city.unworked_tile_overlay);
5289 if (t->sprites.tx.fullfog) {
5290 free(t->sprites.tx.fullfog);
5291 t->sprites.tx.fullfog = NULL;
5294 sprite_vector_free(&t->sprites.colors.overlays);
5295 sprite_vector_free(&t->sprites.explode.unit);
5296 sprite_vector_free(&t->sprites.nation_flag);
5297 sprite_vector_free(&t->sprites.nation_shield);
5298 sprite_vector_free(&t->sprites.citybar.occupancy);
5300 tileset_background_free(t);
5303 /**************************************************************************
5304 Return the sprite for drawing the given spaceship part.
5305 **************************************************************************/
5306 struct sprite *get_spaceship_sprite(const struct tileset *t,
5307 enum spaceship_part part)
5309 return t->sprites.spaceship[part];
5312 /**************************************************************************
5313 Return a sprite for the given citizen. The citizen's type is given,
5314 as well as their index (in the range [0..city_size_get(pcity))). The
5315 citizen's city can be used to determine which sprite to use (a NULL
5316 value indicates there is no city; i.e., the sprite is just being
5317 used as a picture).
5318 **************************************************************************/
5319 struct sprite *get_citizen_sprite(const struct tileset *t,
5320 enum citizen_category type,
5321 int citizen_index,
5322 const struct city *pcity)
5324 const struct citizen_graphic *graphic;
5326 if (type < CITIZEN_SPECIALIST) {
5327 fc_assert(type >= 0);
5328 graphic = &t->sprites.citizen[type];
5329 } else {
5330 fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
5331 graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
5334 return graphic->sprite[citizen_index % graphic->count];
5337 /**************************************************************************
5338 Return the sprite for the nation.
5339 **************************************************************************/
5340 struct sprite *get_nation_flag_sprite(const struct tileset *t,
5341 const struct nation_type *pnation)
5343 return t->sprites.nation_flag.p[nation_index(pnation)];
5346 /**************************************************************************
5347 Return the sprite for the technology/advance.
5348 **************************************************************************/
5349 struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
5351 fc_assert_ret_val(0 <= tech && tech < advance_count(), NULL);
5352 return t->sprites.tech[tech];
5355 /**************************************************************************
5356 Return the sprite for the building/improvement.
5357 **************************************************************************/
5358 struct sprite *get_building_sprite(const struct tileset *t,
5359 struct impr_type *pimprove)
5361 fc_assert_ret_val(NULL != pimprove, NULL);
5362 return t->sprites.building[improvement_index(pimprove)];
5365 /****************************************************************************
5366 Return the sprite for the government.
5367 ****************************************************************************/
5368 struct sprite *get_government_sprite(const struct tileset *t,
5369 const struct government *gov)
5371 fc_assert_ret_val(NULL != gov, NULL);
5372 return t->sprites.government[government_index(gov)];
5375 /****************************************************************************
5376 Return the sprite for the unit type (the base "unit" sprite).
5377 ****************************************************************************/
5378 struct sprite *get_unittype_sprite(const struct tileset *t,
5379 const struct unit_type *punittype,
5380 enum direction8 facing,
5381 bool icon)
5383 int uidx = utype_index(punittype);
5385 fc_assert_ret_val(NULL != punittype, NULL);
5387 if (!is_valid_dir(facing)) {
5388 /* Fallback to using random orientation sprite. */
5389 facing = rand_direction();
5392 if (t->sprites.units.icon[uidx]
5393 && (icon || t->sprites.units.facing[uidx][facing] == NULL)) {
5394 /* Has icon sprite */
5395 return t->sprites.units.icon[uidx];
5396 } else {
5397 return t->sprites.units.facing[uidx][facing];
5401 /**************************************************************************
5402 Return a "sample" sprite for this city style.
5403 **************************************************************************/
5404 struct sprite *get_sample_city_sprite(const struct tileset *t,
5405 int city_style)
5407 int num_thresholds =
5408 t->sprites.city.tile->styles[city_style].land_num_thresholds;
5410 if (num_thresholds == 0) {
5411 return NULL;
5412 } else {
5413 return (t->sprites.city.tile->styles[city_style]
5414 .land_thresholds[num_thresholds - 1].sprite);
5418 /**************************************************************************
5419 Return a sprite with an "arrow" theme graphic.
5420 **************************************************************************/
5421 struct sprite *get_arrow_sprite(const struct tileset *t,
5422 enum arrow_type arrow)
5424 fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, NULL);
5426 return t->sprites.arrow[arrow];
5429 /**************************************************************************
5430 Return a tax sprite for the given output type (usually gold/lux/sci).
5431 **************************************************************************/
5432 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype)
5434 switch (otype) {
5435 case O_SCIENCE:
5436 return t->sprites.tax_science;
5437 case O_GOLD:
5438 return t->sprites.tax_gold;
5439 case O_LUXURY:
5440 return t->sprites.tax_luxury;
5441 case O_TRADE:
5442 case O_FOOD:
5443 case O_SHIELD:
5444 case O_LAST:
5445 break;
5447 return NULL;
5450 /**************************************************************************
5451 Return a thumbs-up/thumbs-down sprite to show treaty approval or
5452 disapproval.
5453 **************************************************************************/
5454 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
5456 return t->sprites.treaty_thumb[on_off ? 1 : 0];
5459 /**************************************************************************
5460 Return a sprite_vector containing the animation sprites for a unit
5461 explosion.
5462 **************************************************************************/
5463 const struct sprite_vector *get_unit_explode_animation(const struct
5464 tileset *t)
5466 return &t->sprites.explode.unit;
5469 /****************************************************************************
5470 Return a sprite contining the single nuke graphic.
5472 TODO: This should be an animation like the unit explode animation.
5473 ****************************************************************************/
5474 struct sprite *get_nuke_explode_sprite(const struct tileset *t)
5476 return t->sprites.explode.nuke;
5479 /**************************************************************************
5480 Return all the sprites used for city bar drawing.
5481 **************************************************************************/
5482 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
5484 if (draw_full_citybar) {
5485 return &t->sprites.citybar;
5486 } else {
5487 return NULL;
5491 /**************************************************************************
5492 Return all the sprites used for editor icons, images, etc.
5493 **************************************************************************/
5494 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
5496 return &t->sprites.editor;
5499 /**************************************************************************
5500 Returns a sprite for the given cursor. The "hot" coordinates (the
5501 active coordinates of the mouse relative to the sprite) are placed int
5502 (*hot_x, *hot_y).
5503 A cursor can consist of several frames to be used for animation.
5504 **************************************************************************/
5505 struct sprite *get_cursor_sprite(const struct tileset *t,
5506 enum cursor_type cursor,
5507 int *hot_x, int *hot_y, int frame)
5509 *hot_x = t->sprites.cursor[cursor].hot_x;
5510 *hot_y = t->sprites.cursor[cursor].hot_y;
5511 return t->sprites.cursor[cursor].frame[frame];
5514 /****************************************************************************
5515 Return a sprite for the given icon. Icons are used by the operating
5516 system/window manager. Usually freeciv has to tell the OS what icon to
5517 use.
5519 Note that this function will return NULL before the sprites are loaded.
5520 The GUI code must be sure to call tileset_load_tiles before setting the
5521 top-level icon.
5522 ****************************************************************************/
5523 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
5525 return t->sprites.icon[icon];
5528 /****************************************************************************
5529 Returns a sprite with the "user-attention" crosshair graphic.
5531 FIXME: This function shouldn't be needed if the attention graphics are
5532 drawn natively by the tileset code.
5533 ****************************************************************************/
5534 struct sprite *get_attention_crosshair_sprite(const struct tileset *t)
5536 return t->sprites.user.attention;
5539 /****************************************************************************
5540 Returns a sprite for the given indicator with the given index. The
5541 index should be in [0, NUM_TILES_PROGRESS).
5542 ****************************************************************************/
5543 struct sprite *get_indicator_sprite(const struct tileset *t,
5544 enum indicator_type indicator,
5545 int index)
5547 index = CLIP(0, index, NUM_TILES_PROGRESS - 1);
5548 fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, NULL);
5549 return t->sprites.indicator[indicator][index];
5552 /****************************************************************************
5553 Return a sprite for the unhappiness of the unit - to be shown as an
5554 overlay on the unit in the city support dialog, for instance.
5556 May return NULL if there's no unhappiness.
5557 ****************************************************************************/
5558 struct sprite *get_unit_unhappy_sprite(const struct tileset *t,
5559 const struct unit *punit,
5560 int happy_cost)
5562 const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
5564 if (unhappy > 0) {
5565 return t->sprites.upkeep.unhappy[unhappy - 1];
5566 } else {
5567 return NULL;
5571 /****************************************************************************
5572 Return a sprite for the upkeep of the unit - to be shown as an overlay
5573 on the unit in the city support dialog, for instance.
5575 May return NULL if there's no unhappiness.
5576 ****************************************************************************/
5577 struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
5578 Output_type_id otype,
5579 const struct unit *punit,
5580 const int *upkeep_cost)
5582 const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES+1);
5584 if (upkeep > 0) {
5585 return t->sprites.upkeep.output[otype][upkeep - 1];
5586 } else {
5587 return NULL;
5591 /****************************************************************************
5592 Return a rectangular sprite containing a fog "color". This can be used
5593 for drawing fog onto arbitrary areas (like the overview).
5594 ****************************************************************************/
5595 struct sprite *get_basic_fog_sprite(const struct tileset *t)
5597 return t->sprites.tx.fog;
5600 /****************************************************************************
5601 Return the tileset's color system.
5602 ****************************************************************************/
5603 struct color_system *get_color_system(const struct tileset *t)
5605 return t->color_system;
5608 /****************************************************************************
5609 Loads prefered theme if there's any.
5610 ****************************************************************************/
5611 void tileset_use_prefered_theme(const struct tileset *t)
5613 char *default_theme_name = NULL;
5614 size_t default_theme_name_sz = 0;
5615 int i;
5617 switch (get_gui_type()) {
5618 case GUI_GTK2:
5619 default_theme_name = gui_gtk2_default_theme_name;
5620 default_theme_name_sz = sizeof(gui_gtk2_default_theme_name);
5621 break;
5622 case GUI_GTK3:
5623 default_theme_name = gui_gtk3_default_theme_name;
5624 default_theme_name_sz = sizeof(gui_gtk3_default_theme_name);
5625 break;
5626 case GUI_SDL:
5627 default_theme_name = gui_sdl_default_theme_name;
5628 default_theme_name_sz = sizeof(gui_sdl_default_theme_name);
5629 break;
5630 case GUI_STUB:
5631 case GUI_XAW:
5632 case GUI_QT:
5633 case GUI_WEB:
5634 break;
5637 if (NULL == default_theme_name || 0 == default_theme_name_sz) {
5638 /* Theme is not supported by this client. */
5639 return;
5642 for (i = 0; i < t->num_prefered_themes; i++) {
5643 if (strcmp(t->prefered_themes[i], default_theme_name)) {
5644 if (popup_theme_suggestion_dialog(t->prefered_themes[i])) {
5645 log_debug("trying theme \"%s\".", t->prefered_themes[i]);
5646 if (load_theme(t->prefered_themes[i])) {
5647 (void) fc_strlcpy(default_theme_name, t->prefered_themes[i],
5648 default_theme_name_sz);
5649 return;
5654 log_verbose("The tileset doesn't specify preferred themes or none of its "
5655 "preferred themes can be used. Using system default.");
5656 gui_clear_theme();
5659 /****************************************************************************
5660 Initialize tileset structure
5661 ****************************************************************************/
5662 void tileset_init(struct tileset *t)
5664 /* We currently have no city sprites loaded. */
5665 t->sprites.city.tile = NULL;
5666 t->sprites.city.wall = NULL;
5667 t->sprites.city.occupied = NULL;
5669 t->sprites.background.color = NULL;
5670 t->sprites.background.graphic = NULL;
5672 player_slots_iterate(pslot) {
5673 int i, j, id = player_slot_index(pslot);
5675 for (i = 0; i < EDGE_COUNT; i++) {
5676 for (j = 0; j < 2; j++) {
5677 t->sprites.player[id].grid_borders[i][j] = NULL;
5681 t->sprites.player[id].color = NULL;
5682 t->sprites.player[id].background = NULL;
5683 } player_slots_iterate_end;
5686 /****************************************************************************
5687 Fill the sprite array with sprites that together make a representative
5688 image of the given terrain type. Suitable for use as an icon and in list
5689 views.
5691 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
5692 Using other values for 'layer' here will result in undefined behaviour. ;)
5693 ****************************************************************************/
5694 int fill_basic_terrain_layer_sprite_array(struct tileset *t,
5695 struct drawn_sprite *sprs,
5696 int layer,
5697 struct terrain *pterrain)
5699 struct drawn_sprite *save_sprs = sprs;
5700 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
5702 struct terrain *tterrain_near[8];
5703 bv_special tspecial_near[8];
5705 struct tile dummy_tile; /* :( */
5707 int i;
5710 memset(&dummy_tile, 0, sizeof(struct tile));
5712 for (i = 0; i < 8; i++) {
5713 tterrain_near[i] = pterrain;
5714 BV_CLR_ALL(tspecial_near[i]);
5717 i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
5718 sprs += fill_terrain_sprite_array(t, sprs, i, &dummy_tile,
5719 pterrain, tterrain_near, draw);
5721 return sprs - save_sprs;
5724 /****************************************************************************
5725 Return the sprite for the given resource type.
5726 ****************************************************************************/
5727 struct sprite *get_resource_sprite(const struct tileset *t,
5728 const struct resource *presource)
5730 if (presource == NULL) {
5731 return NULL;
5734 return t->sprites.resource[resource_index(presource)];
5737 /****************************************************************************
5738 Return a representative sprite for the mine special type (S_MINE).
5739 ****************************************************************************/
5740 struct sprite *get_basic_mine_sprite(const struct tileset *t)
5742 struct drawing_data *draw;
5743 struct terrain *tm;
5745 tm = terrain_by_rule_name("mountains");
5746 if (tm != NULL) {
5747 draw = t->sprites.drawing[terrain_index(tm)];
5748 if (draw->mine != NULL) {
5749 return draw->mine;
5753 terrain_type_iterate(pterrain) {
5754 draw = t->sprites.drawing[terrain_index(pterrain)];
5755 if (draw->mine != NULL) {
5756 return draw->mine;
5758 } terrain_type_iterate_end;
5760 return NULL;
5763 /****************************************************************************
5764 Return a representative sprite for the given special type.
5766 NB: This does not include generic base specials (S_FORTRESS and
5767 S_AIRBASE). Use fill_basic_base_sprite_array and the base type for that.
5768 ****************************************************************************/
5769 struct sprite *get_basic_special_sprite(const struct tileset *t,
5770 enum tile_special_type special)
5772 switch (special) {
5773 case S_IRRIGATION:
5774 return t->sprites.tx.irrigation[0];
5775 break;
5776 case S_MINE:
5777 return get_basic_mine_sprite(t);
5778 break;
5779 case S_POLLUTION:
5780 return t->sprites.tx.pollution;
5781 break;
5782 case S_HUT:
5783 return t->sprites.tx.village;
5784 break;
5785 case S_FARMLAND:
5786 return t->sprites.tx.farmland[0];
5787 break;
5788 case S_FALLOUT:
5789 return t->sprites.tx.fallout;
5790 break;
5791 default:
5792 break;
5795 return NULL;
5798 /****************************************************************************
5799 Fills the sprite array with sprites that together make a representative
5800 image of the given road type. The image is suitable for use as an icon
5801 for the road type, for example.
5802 ****************************************************************************/
5803 int fill_basic_road_sprite_array(const struct tileset *t,
5804 struct drawn_sprite *sprs,
5805 const struct road_type *proad)
5807 struct drawn_sprite *saved_sprs = sprs;
5808 int index;
5809 int i;
5810 enum roadstyle_id roadstyle;
5812 if (!t || !sprs || !proad) {
5813 return 0;
5816 index = road_index(proad);
5818 if (!(0 <= index && index < game.control.num_road_types)) {
5819 return 0;
5822 roadstyle = t->sprites.roads[index].roadstyle;
5824 if (roadstyle == RSTYLE_RIVER) {
5825 ADD_SPRITE_SIMPLE(t->sprites.roads[index].u.rivers.spec[0]);
5826 } else {
5827 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
5828 if (!t->valid_tileset_dirs[i]) {
5829 continue;
5831 if (roadstyle == RSTYLE_ALL_SEPARATE) {
5832 ADD_SPRITE_SIMPLE(t->sprites.roads[index].u.dir[i]);
5833 } else if (roadstyle == RSTYLE_PARITY_COMBINED) {
5834 if ((i % 2) == 0) {
5835 ADD_SPRITE_SIMPLE(t->sprites.roads[index].u.combo.even[1 << (i / 2)]);
5837 } else if (roadstyle == RSTYLE_ALL_COMBINED) {
5838 ADD_SPRITE_SIMPLE(t->sprites.roads[index].u.total[1 << i]);
5843 return sprs - saved_sprs;
5846 /****************************************************************************
5847 Fills the sprite array with sprites that together make a representative
5848 image of the given base type. The image is suitable for use as an icon
5849 for the base type, for example.
5850 ****************************************************************************/
5851 int fill_basic_base_sprite_array(const struct tileset *t,
5852 struct drawn_sprite *sprs,
5853 const struct base_type *pbase)
5855 struct drawn_sprite *saved_sprs = sprs;
5856 int index;
5858 if (!t || !sprs || !pbase) {
5859 return 0;
5862 index = base_index(pbase);
5864 if (!(0 <= index && index < game.control.num_base_types)) {
5865 return 0;
5868 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
5869 if ((x) != NULL) {\
5870 ADD_SPRITE_FULL(x);\
5872 } while (0)
5874 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
5875 ADD_SPRITE_IF_NOT_NULL(t->sprites.bases[index].background);
5876 ADD_SPRITE_IF_NOT_NULL(t->sprites.bases[index].middleground);
5877 ADD_SPRITE_IF_NOT_NULL(t->sprites.bases[index].foreground);
5879 #undef ADD_SPRITE_IF_NOT_NULL
5881 return sprs - saved_sprs;
5884 /****************************************************************************
5885 Setup tiles for one player using the player color.
5886 ****************************************************************************/
5887 void tileset_player_init(struct tileset *t, struct player *pplayer)
5889 int plrid, i, j;
5891 fc_assert_ret(pplayer != NULL);
5892 fc_assert_ret(pplayer->rgb != NULL);
5894 /* Free all data before recreating it. */
5895 tileset_player_free(t, pplayer);
5897 plrid = player_index(pplayer);
5899 t->sprites.player[plrid].color
5900 = create_plr_sprite(ensure_color(pplayer->rgb));
5901 t->sprites.player[plrid].background
5902 = crop_sprite(t->sprites.player[plrid].color, 0, 0,
5903 t->normal_tile_width, t->normal_tile_height,
5904 t->sprites.mask.tile, 0, 0);
5906 for (i = 0; i < EDGE_COUNT; i++) {
5907 for (j = 0; j < 2; j++) {
5908 struct sprite *s;
5910 if (t->sprites.player[plrid].color
5911 && t->sprites.grid.borders[i][j]) {
5912 s = crop_sprite(t->sprites.player[plrid].color, 0, 0,
5913 t->normal_tile_width, t->normal_tile_height,
5914 t->sprites.grid.borders[i][j], 0, 0);
5915 } else {
5916 s = t->sprites.grid.borders[i][j];
5918 t->sprites.player[plrid].grid_borders[i][j] = s;
5923 /****************************************************************************
5924 Free tiles for one player using the player color.
5925 ****************************************************************************/
5926 void tileset_player_free(struct tileset *t, struct player *pplayer)
5928 int plrid, i, j;
5930 fc_assert_ret(pplayer != NULL);
5932 plrid = player_index(pplayer);
5934 if (t->sprites.player[plrid].color) {
5935 free_sprite(t->sprites.player[plrid].color);
5936 t->sprites.player[plrid].color = NULL;
5938 if (t->sprites.player[plrid].background) {
5939 free_sprite(t->sprites.player[plrid].background);
5940 t->sprites.player[plrid].background = NULL;
5943 for (i = 0; i < EDGE_COUNT; i++) {
5944 for (j = 0; j < 2; j++) {
5945 if (t->sprites.player[plrid].grid_borders[i][j]) {
5946 free_sprite(t->sprites.player[plrid].grid_borders[i][j]);
5947 t->sprites.player[plrid].grid_borders[i][j] = NULL;
5953 /****************************************************************************
5954 Setup tiles for the background.
5955 ****************************************************************************/
5956 void tileset_background_init(struct tileset *t)
5958 /* Free all data before recreating it. */
5959 tileset_background_free(t);
5961 /* generate background color */
5962 t->sprites.background.color
5963 = create_plr_sprite(ensure_color(game.plr_bg_color));
5965 /* Chop up and build the background graphics. */
5966 t->sprites.background.graphic
5967 = crop_sprite(t->sprites.background.color, 0, 0,
5968 t->normal_tile_width, t->normal_tile_height,
5969 t->sprites.mask.tile, 0, 0);
5972 /****************************************************************************
5973 Free tiles for the background.
5974 ****************************************************************************/
5975 void tileset_background_free(struct tileset *t)
5977 if (t->sprites.background.color) {
5978 free_sprite(t->sprites.background.color);
5979 t->sprites.background.color = NULL;
5982 if (t->sprites.background.graphic) {
5983 free_sprite(t->sprites.background.graphic);
5984 t->sprites.background.graphic = NULL;
5988 /****************************************************************************
5989 Reset tileset data specific to ruleset.
5990 ****************************************************************************/
5991 void tileset_ruleset_reset(struct tileset *t)
5993 if (t->rivers != NULL) {
5994 road_type_list_destroy(t->rivers);
5996 t->rivers = road_type_list_new();