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