Freeciv-3.4
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.num_city_styles */
47#include "government.h"
48#include "map.h"
49#include "modpack.h"
50#include "movement.h"
51#include "nation.h"
52#include "player.h"
53#include "road.h"
54#include "specialist.h"
55#include "unit.h"
56#include "unitlist.h"
57
58/* client/include */
59#include "dialogs_g.h"
60#include "graphics_g.h"
61#include "gui_main_g.h"
62#include "mapview_g.h" /* For update_map_canvas_visible */
63#include "menu_g.h"
64#include "themes_g.h"
65
66/* client */
67#include "citydlg_common.h" /* For generate_citydlg_dimensions() */
68#include "client_main.h"
69#include "climap.h" /* For client_tile_get_known() */
70#include "colors_common.h"
71#include "control.h" /* For fill_xxx */
72#include "editor.h"
73#include "goto.h"
74#include "gui_properties.h"
75#include "helpdata.h"
76#include "options.h" /* For fill_xxx */
77#include "svgflag.h"
78#include "themes_common.h"
79
80#include "tilespec.h"
81
82#define TILESPEC_CAPSTR "+Freeciv-tilespec-3.4-Devel-2026-Jan-11 duplicates_ok"
83/*
84 * Tilespec capabilities acceptable to this program:
85 *
86 * +Freeciv-3.2-tilespec
87 * - basic format for Freeciv versions 3.2.x; required
88 *
89 * +Freeciv-tilespec-3.2-Devel-YYYY.MMM.DD
90 * - tilespec of the development version at the given date
91 *
92 * duplicates_ok
93 * - we can handle existence of duplicate tags (lattermost tag which
94 * appears is used; tilesets which have duplicates should specify
95 * "duplicates_ok")
96 */
97
98#define SPEC_CAPSTR "+Freeciv-spec-3.4-Devel-2026.Oct.03"
99/*
100 * Individual spec file capabilities acceptable to this program:
101 *
102 * +Freeciv-3.2-spec
103 * - basic format for Freeciv versions 3.2.x; required
104 */
105
106#define TILESPEC_SUFFIX ".tilespec"
107#define TILE_SECTION_PREFIX "tile_"
108
109/* This the way directional indices are now encoded: */
110#define MAX_INDEX_CARDINAL 64
111#define MAX_INDEX_HALF 16
112#define MAX_INDEX_VALID 256
113
114#define NUM_TILES_HP_BAR 11
115#define NUM_TILES_DIGITS 10
116#define MAX_NUM_UPKEEP_SPRITES 10
117
118#define SPECENUM_NAME extrastyle_id
119#define SPECENUM_VALUE0 ESTYLE_ROAD_ALL_SEPARATE
120#define SPECENUM_VALUE0NAME "RoadAllSeparate"
121#define SPECENUM_VALUE1 ESTYLE_ROAD_PARITY_COMBINED
122#define SPECENUM_VALUE1NAME "RoadParityCombined"
123#define SPECENUM_VALUE2 ESTYLE_ROAD_ALL_COMBINED
124#define SPECENUM_VALUE2NAME "RoadAllCombined"
125#define SPECENUM_VALUE3 ESTYLE_RIVER
126#define SPECENUM_VALUE3NAME "River"
127#define SPECENUM_VALUE4 ESTYLE_SINGLE1
128#define SPECENUM_VALUE4NAME "Single1"
129#define SPECENUM_VALUE5 ESTYLE_SINGLE2
130#define SPECENUM_VALUE5NAME "Single2"
131#define SPECENUM_VALUE6 ESTYLE_3LAYER
132#define SPECENUM_VALUE6NAME "3Layer"
133#define SPECENUM_VALUE7 ESTYLE_CARDINALS
134#define SPECENUM_VALUE7NAME "Cardinals"
135#define SPECENUM_COUNT ESTYLE_COUNT
136#include "specenum_gen.h"
137
138/* This could be moved to common/map.h if there's more use for it. */
142static const char direction4letters[4] = "udrl";
143/* This must correspond to enum edge_type. */
144static const char edge_name[EDGE_COUNT][3] = {"ns", "we", "ud", "lr"};
145
146static const int DIR4_TO_DIR8[4] =
148
155
157 CELL_WHOLE, /* Entire tile */
158 CELL_CORNER /* Corner of tile */
160
167
168struct anim {
170 int time;
172 struct sprite **sprites;
174};
175
177 bool init;
178
179 char *name;
180
181 int num_layers; /* 1 thru MAX_NUM_LAYERS. */
182#define MAX_NUM_LAYERS 3
183
187
188#define MAX_NUM_MATCH_WITH 8
191 int match_indices; /* 0 = no match_type, 1 = no match_with */
192
194
197 struct sprite **cells;
198
199 /* List of those sprites in 'cells' that are allocated by some other
200 * means than load_sprite() and thus are not freed by unload_all_sprites(). */
203
205
206 int blending; /* Layer, 0 = none */
208 struct sprite *blend[4]; /* Indexed by a direction4 */
209};
210
212 struct anim *cst;
213};
214
222
228
230 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
231 * sprites, as defined by the tileset. */
232 int count;
234};
235
240
245
247 struct sprite
249 *treaty_thumb[2], /* 0=disagree, 1=agree */
250 *arrow[ARROW_LAST], /* 0=right arrow, 1=plus, 2=minus */
251
253
255
256 /* The panel sprites for showing tax % allocations. */
258 *dither_tile; /* Only used for isometric view */
259
260 struct {
261 struct sprite
266
270
271 struct {
272 struct anim *icon[U_LAST][ACTIVITY_LAST];
275
278
281
283 struct {
284 int hot_x, hot_y;
285 struct sprite *frame[NUM_CURSOR_FRAMES];
287 struct {
289 struct sprite *nuke;
291 struct {
294 struct anim
297 struct sprite
299 *vet_lev[MAX_VET_LEVELS],
305 *go_to, /* goto is a C keyword :-) */
316 *battlegroup[MAX_NUM_BATTLEGROUPS],
320 struct {
321 struct sprite
325 struct {
326 struct sprite
329 *size_tens[NUM_TILES_DIGITS],
330 *size_hundreds[NUM_TILES_DIGITS],
331 *tile_foodnum[NUM_TILES_DIGITS],
332 *tile_shieldnum[NUM_TILES_DIGITS],
333 *tile_tradenum[NUM_TILES_DIGITS];
334 struct city_sprite
339 struct sprite_vector worked_tile_overlay;
340 struct sprite_vector unworked_tile_overlay;
344 struct {
345 struct {
347 struct sprite *turns[NUM_TILES_DIGITS];
348 struct sprite *turns_tens[NUM_TILES_DIGITS];
349 struct sprite *turns_hundreds[NUM_TILES_DIGITS];
353 struct {
357 struct {
358 struct sprite
361 *darkness[MAX_INDEX_CARDINAL]; /* First unused */
362 } tx; /* Terrain extra */
363 struct {
364 struct sprite
368 union {
369 struct anim *single;
370 struct anim *cardinals[MAX_INDEX_CARDINAL];
371 struct {
372 struct anim
376 } bmf;
377 struct {
378 struct anim
379 /* For extrastyles ESTYLE_ROAD_ALL_SEPARATE and ESTYLE_ROAD_PARITY_COMBINED */
381 *corner[8]; /* Indexed by direction; only non-cardinal dirs used. */
382 union {
383 /* For ESTYLE_ROAD_ALL_SEPARATE */
384 struct anim *dir[8]; /* All entries used */
385 /* ESTYLE_ROAD_PARITY_COMBINED */
386 struct {
387 struct anim
388 *even[MAX_INDEX_HALF], /* First unused */
389 *odd[MAX_INDEX_HALF]; /* First unused */
390 } combo;
391 /* ESTYLE_ALL_SEPARATE */
392 struct anim *total[MAX_INDEX_VALID];
393 struct river_sprites rivers;
394 } ru;
396 } u;
398 struct {
399 struct sprite
402 *worked[EDGE_COUNT],
405 *selected[EDGE_COUNT],
406 *coastline[EDGE_COUNT],
407 *borders[EDGE_COUNT][2];
409 struct {
410 struct sprite_vector overlays;
412 struct {
413 struct sprite *color; /* Generic background color */
414 struct sprite *graphic; /* Generic background graphic */
416 struct {
417 struct sprite *grid_borders[EDGE_COUNT][2];
418 struct sprite *color;
421
423};
424
425struct specfile {
426 struct sprite *big_sprite;
427 char *file_name;
428};
429
430#define SPECLIST_TAG specfile
431#define SPECLIST_TYPE struct specfile
432#include "speclist.h"
433
434#define specfile_list_iterate(list, pitem) \
435 TYPED_LIST_ITERATE(struct specfile, list, pitem)
436#define specfile_list_iterate_end LIST_ITERATE_END
437
438/*
439 * Information about an individual sprite. All fields except 'sprite' are
440 * filled at the time of the scan of the specfile. 'Sprite' is
441 * set/cleared on demand in load_sprite()/unload_sprite().
442 */
443struct small_sprite {
444 int ref_count;
445
446 /* The sprite is in this file. */
447 char *file;
448
449 /* Or, the sprite is in this file at the location. */
450 struct specfile *sf;
451 int x, y, width, height;
452
453 /* A little more (optional) data. */
454 int hot_x, hot_y;
455
456 struct sprite *sprite;
457};
458
459/* 'struct small_sprite_list' and related functions. */
460#define SPECLIST_TAG small_sprite
461#define SPECLIST_TYPE struct small_sprite
462#include "speclist.h"
463#define small_sprite_list_iterate(list, pitem) \
464 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
465#define small_sprite_list_iterate_end LIST_ITERATE_END
466
467/* 'struct sprite_hash' and related functions. */
468#define SPECHASH_TAG sprite
469#define SPECHASH_ASTR_KEY_TYPE
470#define SPECHASH_IDATA_TYPE struct small_sprite *
471#include "spechash.h"
472#define sprite_hash_iterate(hash, tag_name, sprite) \
473 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
474 hash, tag_name, sprite)
475#define sprite_hash_iterate_end HASH_ITERATE_END
476
477/* 'struct anim_hash' and related functions. */
478#define SPECHASH_TAG anim
479#define SPECHASH_ASTR_KEY_TYPE
480#define SPECHASH_IDATA_TYPE struct anim *
481#include "spechash.h"
482#define anim_hash_iterate(hash, tag_name, sprite) \
483 TYPED_HASH_ITERATE(const char *, struct anim *, \
484 hash, tag_name, anim)
485#define anim_hash_iterate_end HASH_ITERATE_END
486
487/* 'struct drawing_hash' and related functions. */
488static void drawing_data_destroy(struct drawing_data *draw);
489
490#define SPECHASH_TAG drawing
491#define SPECHASH_CSTR_KEY_TYPE
492#define SPECHASH_IDATA_TYPE struct drawing_data *
493#define SPECHASH_IDATA_FREE drawing_data_destroy
494#include "spechash.h"
495
496#define SPECHASH_TAG estyle
497#define SPECHASH_ASTR_KEY_TYPE
498#define SPECHASH_ENUM_DATA_TYPE extrastyle_id
499#include "spechash.h"
500
501struct tileset {
502 char name[512];
506
507 char *summary;
509 float scale;
510
512
514
518
523
526
528
530
532
535
541
554
555#define NUM_CORNER_DIRS 4
556#define TILES_PER_CORNER 4
560
565
568
569 /* This hash table maps tilespec tags to struct small_sprites. */
571
572 /* This hash table maps terrain graphic strings to drawing data. */
574
576
578
580
582
584
586
589};
590
591struct tileset *tileset = nullptr;
592struct tileset *unscaled_tileset = nullptr;
593
595
596static bool tileset_update = FALSE;
597
598static int global_anim_time = 0;
599
600static struct tileset *tileset_read_toplevel(const char *tileset_name,
601 bool verbose, int topology_id,
602 float scale);
603
604static int fill_unit_type_sprite_array(const struct tileset *t,
605 struct drawn_sprite *sprs,
606 const struct unit_type *putype,
607 enum unit_activity activity,
608 enum direction8 facing);
609static int fill_unit_sprite_array(const struct tileset *t,
610 struct drawn_sprite *sprs,
611 const struct unit *punit,
612 int stack, bool backdrop);
613static bool load_river_sprites(struct tileset *t,
614 struct river_sprites *store, const char *tag_pfx);
615
616static void tileset_setup_base(struct tileset *t,
617 const struct extra_type *pextra,
618 const char *tag);
619static void tileset_setup_road(struct tileset *t,
620 struct extra_type *pextra,
621 const char *tag);
622
623static bool is_extra_drawing_enabled(struct extra_type *pextra);
624
625static int fill_basic_road_sprite_array(const struct tileset *t,
626 struct drawn_sprite *sprs,
627 const struct extra_type *pextra);
628static int fill_basic_base_sprite_array(const struct tileset *t,
629 struct drawn_sprite *sprs,
630 const struct extra_type *pextra);
631
632static void tileset_player_free(struct tileset *t, int plrid);
633
634static void tileset_setup_specialist_type(struct tileset *t,
635 struct citizen_set *set,
637 const char *tag_group,
638 const char *set_name,
639 bool required);
641static void tileset_setup_citizen_types(struct tileset *t,
642 struct citizen_set *set,
643 const char *tag_group,
644 const char *set_name,
645 bool required);
646
647/************************************************************************/
650void tileset_error(enum log_level level, const char *tset_name,
651 const char *format, ...)
652{
653 char buf[2048];
654 va_list args;
655
656 va_start(args, format);
657 fc_vsnprintf(buf, sizeof(buf), format, args);
658 va_end(args);
659
660 log_base(level, "%s", buf);
661
662 if (level <= LOG_NORMAL) {
664
665 if (level == LOG_FATAL) {
667 }
668 }
669}
670
671/************************************************************************/
674static struct drawing_data *drawing_data_new(void)
675{
676 struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
677
678 draw->name = nullptr;
679
680 return draw;
681}
682
683/************************************************************************/
687{
688 int i;
689
690 fc_assert_ret(draw != nullptr);
691
692 if (draw->name != nullptr) {
693 free(draw->name);
694 }
695 for (i = 0; i < 4; i++) {
696 if (draw->blend[i]) {
697 free_sprite(draw->blend[i]);
698 }
699 }
700 for (i = 0; i < draw->num_layers; i++) {
701 int vec_size = sprite_vector_size(&draw->layer[i].allocated);
702 int j;
703
704 for (j = 0; j < vec_size; j++) {
705 free_sprite(draw->layer[i].allocated.p[j]);
706 }
707
708 sprite_vector_free(&draw->layer[i].base);
709 sprite_vector_free(&draw->layer[i].allocated);
710 free(draw->layer[i].cells);
711 }
712 free(draw);
713}
714
715/************************************************************************/
718struct tileset *get_tileset(void)
719{
720 if (unscaled_tileset != nullptr) {
721 return unscaled_tileset;
722 } else {
723 return tileset;
724 }
725}
726
727/************************************************************************/
730const char *tileset_basename(const struct tileset *t)
731{
732 return t->name;
733}
734
735/************************************************************************/
738bool tileset_is_isometric(const struct tileset *t)
739{
740 return t->type == TS_ISOMETRIC;
741}
742
743/************************************************************************/
747int tileset_hex_width(const struct tileset *t)
748{
749 return t->hex_width;
750}
751
752/************************************************************************/
756int tileset_hex_height(const struct tileset *t)
757{
758 return t->hex_height;
759}
760
761/************************************************************************/
779int tileset_tile_width(const struct tileset *t)
780{
781 return t->normal_tile_width;
782}
783
784/************************************************************************/
791int tileset_tile_height(const struct tileset *t)
792{
793 return t->normal_tile_height;
794}
795
796/************************************************************************/
803{
804 return t->full_tile_width;
805}
806
807/************************************************************************/
816{
817 return t->full_tile_height;
818}
819
820/************************************************************************/
823int tileset_unit_width(const struct tileset *t)
824{
825 return t->unit_tile_width;
826}
827
828/************************************************************************/
831int tileset_unit_height(const struct tileset *t)
832{
833 return t->unit_tile_height;
834}
835
836/************************************************************************/
839static int calculate_max_upkeep_height(const struct tileset *t)
840{
841 int i;
842 int max = 0;
843
844 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
845 if (t->sprites.upkeep.unhappy[i] != nullptr) {
846 int width, height;
847
848 /* TODO: We want only height, getting the width might waste CPU
849 * depending on gui-specific implementation. */
851
852 max = MAX(max, height);
853 }
854 }
855
857 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
858 if (t->sprites.upkeep.output[o][i] != nullptr) {
859 int width, height;
860
861 /* TODO: We want only height, getting the width might waste CPU
862 * depending on gui-specific implementation. */
864
865 max = MAX(max, height);
866 }
867 }
869
870 return max;
871}
872
873/************************************************************************/
876static int tileset_upkeep_height(const struct tileset *t)
877{
878 /* Return cached value */
879 return t->max_upkeep_height;
880}
881
882/************************************************************************/
892
893/************************************************************************/
904
905/************************************************************************/
909{
910 return t->unit_upkeep_offset_y;
911}
912
913/************************************************************************/
918{
920}
921
922/************************************************************************/
928{
929 return t->small_sprite_width;
930}
931
932/************************************************************************/
937{
938 return t->citybar_offset_y;
939}
940
941/************************************************************************/
946{
947 return t->tilelabel_offset_y;
948}
949
950/************************************************************************/
953float tileset_scale(const struct tileset *t)
954{
955 return tileset->scale;
956}
957
958/************************************************************************/
964{
965 return t->small_sprite_height;
966}
967
968/************************************************************************/
973const char *tileset_main_intro_filename(const struct tileset *t)
974{
975 return t->main_intro_filename;
976}
977
978/************************************************************************/
982{
983 return t->sprites.city.worked_tile_overlay.size;
984}
985
986/************************************************************************/
990{
991 return FOG_AUTO == t->fogstyle;
992}
993
994/************************************************************************/
997static struct tileset *tileset_new(void)
998{
999 struct tileset *t = fc_calloc(1, sizeof(*t));
1000
1003
1004 return t;
1005}
1006
1007/************************************************************************/
1011static const char *dir_get_tileset_name(enum direction8 dir)
1012{
1013 switch (dir) {
1014 case DIR8_NORTH:
1015 return "n";
1016 case DIR8_NORTHEAST:
1017 return "ne";
1018 case DIR8_EAST:
1019 return "e";
1020 case DIR8_SOUTHEAST:
1021 return "se";
1022 case DIR8_SOUTH:
1023 return "s";
1024 case DIR8_SOUTHWEST:
1025 return "sw";
1026 case DIR8_WEST:
1027 return "w";
1028 case DIR8_NORTHWEST:
1029 return "nw";
1030 }
1031 log_error("Wrong direction8 variant: %d.", dir);
1032 return "";
1033}
1034
1035/************************************************************************/
1038static enum direction8 dir_by_tileset_name(const char *str)
1039{
1040 enum direction8 dir;
1041
1042 for (dir = direction8_begin();
1043 dir != direction8_end();
1044 dir = direction8_next(dir)) {
1045 if (strcmp(dir_get_tileset_name(dir), str) == 0) {
1046 return dir;
1047 }
1048 }
1049
1050 return direction8_invalid();
1051}
1052
1053/************************************************************************/
1056static bool is_valid_tileset_dir(const struct tileset *t,
1057 enum direction8 dir)
1058{
1059 if (t->hex_width > 0) {
1060 return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
1061 } else if (t->hex_height > 0) {
1062 return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
1063 } else {
1064 return TRUE;
1065 }
1066}
1067
1068/************************************************************************/
1074static bool is_cardinal_tileset_dir(const struct tileset *t,
1075 enum direction8 dir)
1076{
1077 if (t->hex_width > 0 || t->hex_height > 0) {
1078 return is_valid_tileset_dir(t, dir);
1079 } else {
1080 return (dir == DIR8_NORTH || dir == DIR8_EAST
1081 || dir == DIR8_SOUTH || dir == DIR8_WEST);
1082 }
1083}
1084
1085/************************************************************************/
1090{
1091 int idx;
1092
1093 if ((actual_topology & TF_HEX)
1094 && (actual_topology & TF_ISO)) {
1095 idx = TS_TOPO_ISOHEX;
1096 } else if (actual_topology & TF_ISO) {
1097 idx = TS_TOPO_SQUARE;
1098 } else if (actual_topology & TF_HEX) {
1099 idx = TS_TOPO_HEX;
1100 } else {
1101 idx = TS_TOPO_SQUARE;
1102 }
1103
1104 return idx;
1105}
1106
1107/************************************************************************/
1112{
1113 switch (idx) {
1114 case TS_TOPO_SQUARE:
1115 return TF_ISO;
1116 case TS_TOPO_HEX:
1117 return TF_HEX;
1118 case TS_TOPO_ISOHEX:
1119 return TF_HEX | TF_ISO;
1120 }
1121
1122 return 0;
1123}
1124
1126 struct strvec *list;
1127 int topo;
1128};
1129
1130/************************************************************************/
1133static void ts_list_cb(const char *modpack_name, const char *filename,
1134 void *data)
1135{
1136 struct ts_list_data *tsdata = (struct ts_list_data *)data;
1137 const char *target = modpack_tileset_target(modpack_name);
1138 struct tileset *t = tileset_read_toplevel(target,
1139 FALSE, tsdata->topo, 1.0f);
1140
1141 if (t != nullptr) {
1142 strvec_append(tsdata->list, target);
1143 tileset_free(t);
1144 }
1145}
1146
1147/************************************************************************/
1150const struct strvec *get_tileset_list(const struct option *poption)
1151{
1152 static struct strvec *tilesets[3] = { nullptr, nullptr, nullptr };
1153 int topo = option_get_cb_data(poption);
1154 int idx;
1155
1156 idx = ts_topology_index(topo);
1157
1158 fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), nullptr);
1159
1160 if (tilesets[idx] == nullptr) {
1161 struct ts_list_data data;
1162
1163 /* Note: this means you must restart the client after installing a new
1164 tileset. */
1165 tilesets[idx] = strvec_new();
1166 data.list = tilesets[idx];
1167 data.topo = topo;
1169 }
1170
1171 return tilesets[idx];
1172}
1173
1174/************************************************************************/
1181static char *tilespec_fullname(const char *tileset_name)
1182{
1183 if (tileset_name) {
1185 const char *dname;
1186
1187 fc_snprintf(fname, sizeof(fname),
1188 "%s%s", tileset_name, TILESPEC_SUFFIX);
1189
1191
1192 if (dname) {
1193 return fc_strdup(dname);
1194 }
1195 }
1196
1197 return nullptr;
1198}
1199
1200/************************************************************************/
1206 const char *which,
1207 const char *us_capstr,
1208 const char *filename,
1209 bool verbose)
1210{
1211 enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
1212
1213 const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
1214
1215 if (file_capstr == nullptr) {
1216 log_base(level, "\"%s\": %s file doesn't have a capability string",
1217 filename, which);
1218 return FALSE;
1219 }
1221 log_base(level, "\"%s\": %s file appears incompatible:",
1222 filename, which);
1223 log_base(level, " datafile options: %s", file_capstr);
1224 log_base(level, " supported options: %s", us_capstr);
1225 return FALSE;
1226 }
1228 log_base(level, "\"%s\": %s file requires option(s) "
1229 "that client doesn't support:", filename, which);
1230 log_base(level, " datafile options: %s", file_capstr);
1231 log_base(level, " supported options: %s", us_capstr);
1232 return FALSE;
1233 }
1234
1235 return TRUE;
1236}
1237
1238/************************************************************************/
1243static void tileset_free_toplevel(struct tileset *t)
1244{
1245 int i, j;
1246
1247 if (t->main_intro_filename) {
1249 t->main_intro_filename = nullptr;
1250 }
1251
1252 if (t->preferred_themes) {
1253 for (i = 0; i < t->num_preferred_themes; i++) {
1254 free(t->preferred_themes[i]);
1255 }
1257 t->preferred_themes = nullptr;
1258 }
1259 t->num_preferred_themes = 0;
1260
1261 if (t->tile_hash) {
1263 t->tile_hash = nullptr; /* Helpful for sanity. */
1264 }
1265 if (t->estyle_hash) {
1267 t->estyle_hash = nullptr;
1268 }
1269 for (i = 0; i < ESTYLE_COUNT; i++) {
1270 if (t->style_lists[i] != nullptr) {
1272 t->style_lists[i] = nullptr;
1273 }
1274 }
1275
1276 if (t->flagged_bases_list != nullptr) {
1278 t->flagged_bases_list = nullptr;
1279 }
1280
1281 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1282 struct tileset_layer *tslp = &t->layers[i];
1283
1284 if (tslp->match_types) {
1285 for (j = 0; j < tslp->match_count; j++) {
1286 free(tslp->match_types[j]);
1287 }
1288 free(tslp->match_types);
1289 tslp->match_types = nullptr;
1290 }
1291 }
1292
1293 if (t->color_system) {
1295 t->color_system = nullptr;
1296 }
1297
1298 if (t->summary != nullptr) {
1299 free(t->summary);
1300 t->summary = nullptr;
1301 }
1302 if (t->description != nullptr) {
1303 free(t->description);
1304 t->description = nullptr;
1305 }
1306 if (t->for_ruleset != nullptr) {
1307 free(t->for_ruleset);
1308 t->for_ruleset = nullptr;
1309 }
1310}
1311
1312/************************************************************************/
1315void tileset_free(struct tileset *t)
1316{
1317 int i;
1318
1321 for (i = 0; i < ARRAY_SIZE(t->sprites.player); i++) {
1323 }
1326 free(t);
1327}
1328
1329/************************************************************************/
1332static void ts_cb(const char *modpack_name, const char *filename, void *data)
1333{
1334 int topo_id = *((int *)data);
1335 struct tileset *t = tileset_read_toplevel(modpack_tileset_target(modpack_name),
1336 FALSE, topo_id, 1.0f);
1337
1338 if (t != nullptr) {
1339 if (tileset == nullptr) {
1340 tileset = t;
1341 } else if (t->priority > tileset->priority
1342 || (topo_id >= 0
1345 tileset = t;
1346 } else {
1347 tileset_free(t);
1348 }
1349 }
1350}
1351
1352/************************************************************************/
1360bool tilespec_try_read(const char *tileset_name, bool verbose, int topo_id,
1361 bool global_default)
1362{
1363 bool original;
1364
1365 if (tileset_name == nullptr
1367 topo_id, 1.0f))) {
1368 original = FALSE;
1370
1371 if (tileset == nullptr) {
1372 tileset_error(LOG_FATAL, nullptr, _("No usable default tileset found, aborting!"));
1373 }
1374
1375 log_verbose("Trying tileset \"%s\".", tileset->name);
1376 } else {
1377 original = TRUE;
1378 }
1380
1381 if (global_default) {
1383 }
1384
1385 return original;
1386}
1387
1388/************************************************************************/
1402 bool game_fully_initialized, float scale)
1403{
1404 int id;
1405 struct tile *center_tile;
1406 enum client_states state = client_state();
1408 char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1409 bool new_tileset_in_use;
1410 int ts_topo;
1411
1412 /* Make local copies since these values may be freed down below */
1414 sz_strlcpy(old_name, tileset->name);
1415
1416 log_normal(_("Loading tileset \"%s\"."), tileset_name);
1417
1418 /* Step 0: Record old data.
1419 *
1420 * We record the current mapcanvas center, etc.
1421 */
1423
1424 /* Step 1: Cleanup.
1425 *
1426 * Free old tileset or keep it in memory if we are loading the same
1427 * tileset with scaling and old one was not scaled.
1428 */
1429
1430 if (strcmp(tileset_name, old_name) == 0 && tileset->scale == 1.0f
1431 && scale != 1.0f) {
1432 if (unscaled_tileset) {
1434 }
1436 } else {
1438 }
1439
1440 /* Step 2: Read.
1441 *
1442 * We read in the new tileset. This should be pretty straightforward.
1443 */
1445 if (tileset != nullptr) {
1447 } else {
1449
1450 if (!(tileset = tileset_read_toplevel(old_name, FALSE, -1, scale))) {
1451 log_fatal("Failed to re-read the currently loaded tileset.");
1453 }
1454 }
1458 }
1459
1463 } /* else we'll get round to it on PACKET_RULESET_GAME */
1464 players_iterate(pplayer) {
1465 tileset_player_init(tileset, pplayer);
1467 boot_help_texts(); /* "About Current Tileset" */
1468 }
1469
1470 /* Step 3: Setup
1471 *
1472 * This is a seriously sticky problem. On startup, we build a hash
1473 * from all the sprite data. Then, when we connect to a server, the
1474 * server sends us ruleset data a piece at a time and we use this data
1475 * to assemble the sprite structures. But if we change while connected
1476 * we have to reassemble all of these. This should just involve
1477 * calling tilespec_setup_*** on everything. But how do we tell what
1478 * "everything" is?
1479 *
1480 * The below code just does things straightforwardly, by setting up
1481 * each possible sprite again. Hopefully it catches everything, and
1482 * doesn't mess up too badly if we change tilesets while not connected
1483 * to a server.
1484 */
1485 if (!game.client.ruleset_ready) {
1486 /* The ruleset data is not sent until this point. */
1487 return new_tileset_in_use;
1488 }
1489
1491 == TOPO_INCOMP_HARD) {
1493 _("Map topology (%s) and tileset (%s) incompatible."),
1495 }
1496
1497 terrain_type_iterate(pterrain) {
1503 governments_iterate(gov) {
1506 extra_type_iterate(pextra) {
1509 nations_iterate(pnation) {
1512 improvement_iterate(pimprove) {
1521
1524 * sizeof(tileset->sprites.style_citizen_sets.sets[0]));
1525
1526 for (id = 0; id < game.control.num_city_styles; id++) {
1528 }
1529
1530 if (state < C_S_RUNNING) {
1531 /* Below redraws do not apply before this. */
1532 return new_tileset_in_use;
1533 }
1534
1535 /* Step 4: Draw.
1536 *
1537 * Do any necessary redraws.
1538 */
1541 can_slide = FALSE;
1543 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1544 * drawing we might not get one. Of course this is slower. */
1546 can_slide = TRUE;
1547
1548 return new_tileset_in_use;
1549}
1550
1551/************************************************************************/
1556{
1557 const char *tileset_name;
1558 enum client_states state = client_state();
1559
1560 if (state == C_S_RUNNING || state == C_S_OVER) {
1562
1563 /* Also iso map topology counts as 'square' tileset topology */
1564 if (opt != (wld.map.topology_id & (TF_ISO | TF_HEX))
1565 && (opt != 0 || ((wld.map.topology_id & TF_HEX) == TF_HEX))) {
1566 /* Changed option was not for current topology */
1567 return;
1568 }
1569 }
1570
1572
1573 fc_assert_ret(tileset_name != nullptr && tileset_name[0] != '\0');
1574
1577
1578 /* As it's going to be 'current' tileset, make it global default if
1579 * options saved. */
1581
1583 menus_init();
1584}
1585
1586/************************************************************************/
1593{
1595 tilespec_reread(tname, TRUE, 1.0f);
1597 menus_init();
1598}
1599
1600/************************************************************************/
1604static struct sprite *load_gfx_file(const char *gfx_filename, bool svgflag)
1605{
1606 const char **gfx_fileexts, *gfx_fileext;
1607 struct sprite *s;
1608
1609 if (svgflag) {
1611 } else {
1613 }
1614
1615 /* Try out all supported file extensions to find one that works. */
1616 while ((gfx_fileext = *gfx_fileexts++)) {
1617 const char *real_full_name;
1618 char full_name[strlen(gfx_filename) + strlen(".")
1619 + strlen(gfx_fileext) + 1];
1620
1623 log_debug("trying to load gfx file \"%s\".", real_full_name);
1625 svgflag && !strcmp("svg", gfx_fileext));
1626 if (s) {
1627 return s;
1628 }
1629 }
1630 }
1631
1632 log_error("Could not load gfx file \"%s\".", gfx_filename);
1633
1634 return nullptr;
1635}
1636
1637/************************************************************************/
1640static void ensure_big_sprite(struct specfile *sf, const char *tset_name)
1641{
1642 struct section_file *file;
1643 const char *gfx_filename;
1644
1645 if (sf->big_sprite) {
1646 /* Looks like it's already loaded. */
1647 return;
1648 }
1649
1650 /* Otherwise load it. The big sprite will sometimes be freed and will have
1651 * to be reloaded, but most of the time it's just loaded once, the small
1652 * sprites are extracted, and then it's freed. */
1653 if (!(file = secfile_load(sf->file_name, TRUE))) {
1655 _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1656 }
1657
1658 if (!check_tilespec_capabilities(file, "spec",
1659 SPEC_CAPSTR, sf->file_name, TRUE)) {
1661 _("Specfile %s has incompatible capabilities"), sf->file_name);
1662 }
1663
1664 gfx_filename = secfile_lookup_str(file, "file.gfx");
1665
1667
1668 if (!sf->big_sprite) {
1670 _("Could not load gfx file for the spec file \"%s\"."),
1671 sf->file_name);
1672 }
1673 secfile_destroy(file);
1674}
1675
1676/************************************************************************/
1681static void scan_specfile(struct tileset *t, struct specfile *sf,
1682 bool duplicates_ok)
1683{
1684 struct section_file *file;
1685 struct section_list *sections;
1686 int i;
1687
1688 if (!(file = secfile_load(sf->file_name, TRUE))) {
1690 _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1691 }
1692 if (!check_tilespec_capabilities(file, "spec",
1693 SPEC_CAPSTR, sf->file_name, TRUE)) {
1695 _("Specfile %s has incompatible capabilities"), sf->file_name);
1696 }
1697
1698 /* Currently unused */
1699 secfile_entry_ignore(file, "info.artists");
1700
1701 /* Not used here */
1702 secfile_entry_ignore(file, "file.gfx");
1703
1704 if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1705 section_list_iterate(sections, psection) {
1706 int j, k;
1707 int x_top_left, y_top_left, dx, dy;
1708 int pixel_border_x;
1709 int pixel_border_y;
1710 const char *sec_name = section_name(psection);
1711
1712 pixel_border_x = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1713 sec_name);
1714 pixel_border_y = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_y",
1715 sec_name);
1716 pixel_border_x = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_x",
1717 sec_name);
1718 if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1719 || !secfile_lookup_int(file, &y_top_left,
1720 "%s.y_top_left", sec_name)
1721 || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1722 || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1723 log_error("%s grid \"%s\" invalid: %s",
1725 continue;
1726 }
1727
1728 j = -1;
1729 while (secfile_entry_lookup(file, "%s.tiles%d.tag",
1730 sec_name, ++j) != nullptr) {
1731 struct small_sprite *ss;
1732 int row, column;
1733 int xr, yb;
1734 const char **tags;
1735 size_t num_tags;
1736 int hot_x, hot_y;
1737
1738 if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1739 || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1740 sec_name, j)
1741 || !(tags = secfile_lookup_str_vec(file, &num_tags,
1742 "%s.tiles%d.tag",
1743 sec_name, j))) {
1744 log_error("%s small sprite \"%s.tiles%d\" invalid: %s",
1746 continue;
1747 }
1748 hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1749 sec_name, j);
1750 hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1751 sec_name, j);
1752
1753 /* There must be at least 1 because of the while(): */
1754 fc_assert_action(num_tags > 0, continue);
1755
1756 xr = x_top_left + (dx + pixel_border_x) * column;
1757 yb = y_top_left + (dy + pixel_border_y) * row;
1758
1759 ss = fc_malloc(sizeof(*ss));
1760 ss->ref_count = 0;
1761 ss->file = nullptr;
1762 ss->x = xr;
1763 ss->y = yb;
1764 ss->width = dx;
1765 ss->height = dy;
1766 ss->sf = sf;
1767 ss->sprite = nullptr;
1768 ss->hot_x = hot_x;
1769 ss->hot_y = hot_y;
1770
1772
1773 if (!duplicates_ok) {
1774 for (k = 0; k < num_tags; k++) {
1775 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1776 log_error("warning: %s already has a sprite for \"%s\".",
1777 tileset_name_get(t), tags[k]);
1778 }
1779 }
1780 } else {
1781 for (k = 0; k < num_tags; k++) {
1782 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1783 }
1784 }
1785
1786 free(tags);
1787 tags = nullptr;
1788 }
1790 section_list_destroy(sections);
1791 }
1792
1793 /* Load "extra" sprites. Each sprite is one file. */
1794 i = -1;
1795 while (secfile_entry_lookup(file, "extra.sprites%d.tag", ++i) != nullptr) {
1796 struct small_sprite *ss;
1797 const char **tags;
1798 const char *filename;
1799 size_t num_tags, k;
1800 int hot_x, hot_y;
1801
1802 if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1803 "extra.sprites%d.tag", i))
1804 || !(filename = secfile_lookup_str(file,
1805 "extra.sprites%d.file", i))) {
1806 log_error("%s extra sprite \"extra.sprites%d\" invalid: %s",
1808 continue;
1809 }
1810 hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1811 hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1812
1813 ss = fc_malloc(sizeof(*ss));
1814 ss->ref_count = 0;
1815 ss->file = fc_strdup(filename);
1816 ss->sf = nullptr;
1817 ss->sprite = nullptr;
1818 ss->hot_x = hot_x;
1819 ss->hot_y = hot_y;
1820
1822
1823 if (!duplicates_ok) {
1824 for (k = 0; k < num_tags; k++) {
1825 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1826 log_error("warning: %s already have a sprite for \"%s\".",
1827 tileset_name_get(t), tags[k]);
1828 }
1829 }
1830 } else {
1831 for (k = 0; k < num_tags; k++) {
1832 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1833 }
1834 }
1835 free(tags);
1836 }
1837
1840}
1841
1842/************************************************************************/
1846static char *tilespec_gfx_filename(const char *gfx_filename,
1847 const char *tset_name)
1848{
1849 const char *gfx_current_fileext;
1850 const char **gfx_fileexts = gfx_fileextensions();
1851
1852 while ((gfx_current_fileext = *gfx_fileexts++)) {
1853 const char *real_full_name;
1854 char *full_name =
1857
1859
1861 free(full_name);
1862 if (real_full_name) {
1863 return fc_strdup(real_full_name);
1864 }
1865 }
1866
1868 _("Couldn't find a supported gfx file extension for \"%s\"."),
1869 gfx_filename);
1870
1871 return nullptr;
1872}
1873
1874/************************************************************************/
1877static bool tileset_scan_single_list(struct tileset *t,
1878 const char *spec_filenames[],
1879 int num_spec_files, bool verbose,
1880 bool duplicates_ok)
1881{
1882 int i;
1883
1884 for (i = 0; i < num_spec_files; i++) {
1885 struct specfile *sf = fc_malloc(sizeof(*sf));
1886 const char *dname;
1887
1888 log_debug("spec file %s", spec_filenames[i]);
1889
1890 sf->big_sprite = nullptr;
1892 if (!dname) {
1893 if (verbose) {
1894 log_error("Can't find spec file \"%s\".", spec_filenames[i]);
1895 }
1896
1897 return FALSE;
1898 }
1899 sf->file_name = fc_strdup(dname);
1901
1903 }
1904
1905 return TRUE;
1906}
1907
1908/************************************************************************/
1911static int check_sprite_type(const char *sprite_type, const char *tile_section)
1912{
1913 if (fc_strcasecmp(sprite_type, "corner") == 0) {
1914 return CELL_CORNER;
1915 }
1916 if (fc_strcasecmp(sprite_type, "single") == 0) {
1917 return CELL_WHOLE;
1918 }
1919 if (fc_strcasecmp(sprite_type, "whole") == 0) {
1920 return CELL_WHOLE;
1921 }
1922 log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1923 return CELL_WHOLE;
1924}
1925
1926/************************************************************************/
1932static struct tileset *tileset_read_toplevel(const char *tileset_name,
1933 bool verbose, int topology_id,
1934 float scale)
1935{
1936 struct section_file *file;
1937 char *fname;
1938 const char *c;
1939 int i;
1940 size_t num_spec_files[SFILE_LAST];
1941 const char **spec_filenames[SFILE_LAST];
1942 size_t num_layers;
1943 const char **layer_order;
1944 size_t num_preferred_themes;
1945 struct section_list *sections = nullptr;
1946 const char *file_capstr;
1947 bool duplicates_ok, is_hex;
1948 enum direction8 dir;
1949 struct tileset *t = nullptr;
1950 const char *extraname;
1951 const char *tstr;
1952 int topo;
1953 bool svg;
1955 const char *type_name;
1956 bool vsup;
1957
1959
1960 if (fname == nullptr) {
1961 if (verbose) {
1962 log_error("Can't find tileset \"%s\".", tileset_name);
1963 }
1964
1965 return nullptr;
1966 }
1967 log_verbose("tilespec file is \"%s\".", fname);
1968
1969 if (!(file = secfile_load(fname, TRUE))) {
1970 log_error("Could not open '%s':\n%s", fname, secfile_error());
1971 free(fname);
1972
1973 return nullptr;
1974 }
1975
1976 if (!check_tilespec_capabilities(file, "tilespec",
1977 TILESPEC_CAPSTR, fname, verbose)) {
1978 secfile_destroy(file);
1979 free(fname);
1980
1981 return nullptr;
1982 }
1983
1984 t = tileset_new();
1985 t->scale = scale;
1986 file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1987 duplicates_ok = (file_capstr != nullptr
1988 && has_capabilities("+duplicates_ok", file_capstr));
1989
1990 tstr = secfile_lookup_str(file, "tilespec.name");
1991 /* Tileset name found */
1993 tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1994 if (tstr[0] != '\0') {
1995 /* Tileset version found */
1996 sz_strlcpy(t->version, tstr);
1997 } else {
1998 /* No version information */
1999 t->version[0] = '\0';
2000 }
2001
2002 tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
2003 if (tstr[0] != '\0') {
2004 int len;
2005
2006 /* Tileset summary found */
2007 len = strlen(tstr);
2008 t->summary = fc_malloc(len + 1);
2009 fc_strlcpy(t->summary, tstr, len + 1);
2010 } else {
2011 /* No summary */
2012 if (t->summary != nullptr) {
2013 free(t->summary);
2014 t->summary = nullptr;
2015 }
2016 }
2017
2018 tstr = secfile_lookup_str_default(file, "", "tilespec.description");
2019 if (tstr[0] != '\0') {
2020 int len;
2021
2022 /* Tileset description found */
2023 len = strlen(tstr);
2024 t->description = fc_malloc(len + 1);
2025 fc_strlcpy(t->description, tstr, len + 1);
2026 } else {
2027 /* No description */
2028 if (t->description != nullptr) {
2029 free(t->description);
2030 t->description = nullptr;
2031 }
2032 }
2033
2034 tstr = secfile_lookup_str_default(file, nullptr, "tilespec.for_ruleset");
2035 if (tstr != nullptr) {
2037 } else {
2038 t->for_ruleset = nullptr;
2039 }
2040
2042 if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
2043 || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
2044 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2045 goto ON_ERROR;
2046 }
2047
2048 tstr = secfile_lookup_str(file, "tilespec.type");
2049 if (tstr == nullptr) {
2050 log_error("Tileset \"%s\": no tileset type", t->name);
2051 goto ON_ERROR;
2052 }
2053
2055 if (!ts_type_is_valid(t->type)) {
2056 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
2057 goto ON_ERROR;
2058 }
2059
2060 if (t->type == TS_ISOMETRIC) {
2061 topo = TF_ISO;
2062 } else {
2063 topo = 0;
2064 }
2065
2066 /* Read hex-tileset information. */
2067 t->hex_width = t->hex_height = 0;
2068 if (is_hex) {
2069 int hex_side;
2070
2071 if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
2072 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2073 goto ON_ERROR;
2074 }
2075 hex_side = hex_side * t->scale;
2076 if (t->type == TS_ISOMETRIC) {
2077 t->hex_width = hex_side;
2078 } else {
2079 t->hex_height = hex_side;
2080 }
2081
2082 topo |= TF_HEX;
2083
2084 /* Hex tilesets are drawn the same as isometric. */
2085 /* FIXME: There will be other legal values to be used with hex
2086 * tileset in the future, and this would just overwrite it. */
2087 t->type = TS_ISOMETRIC;
2088 }
2089
2090 if (topology_id >= 0) {
2091 if (((topology_id & TF_HEX) && topology_id != (topo & (TF_ISO | TF_HEX)))
2092 || (!(topology_id & TF_HEX) && (topo & TF_HEX))) {
2093 /* Not of requested topology */
2094 goto ON_ERROR;
2095 }
2096 }
2097
2098 t->ts_topo_idx = ts_topology_index(topo);
2099
2100 /* Needed for older compilers to not give "used uninitialized" warning */
2101 vsup = FALSE;
2102
2103 switch (t->type) {
2104 case TS_ISOMETRIC:
2106 break;
2107 case TS_OVERHEAD:
2109 break;
2110 case TS_3D:
2112 break;
2113 }
2114
2115 if (!vsup) {
2116 /* TRANS: "Overhead" or "Isometric" */
2117 log_normal(_("Client does not support %s tilesets."),
2118 _(ts_type_name(t->type)));
2119 log_normal(_("Using default tileset instead."));
2120
2121 fc_assert(tileset_name != nullptr);
2122
2123 goto ON_ERROR;
2124 }
2125
2127
2128 /* Create arrays of valid and cardinal tileset dirs. These depend
2129 * entirely on the tileset, not the topology. They are also in clockwise
2130 * rotational ordering. */
2132 dir = DIR8_NORTH;
2133 do {
2134 if (is_valid_tileset_dir(t, dir)) {
2137 }
2138 if (is_cardinal_tileset_dir(t, dir)) {
2141 }
2142
2143 dir = dir_cw(dir);
2144 } while (dir != DIR8_NORTH);
2145
2146 fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
2149
2151 "tilespec.normal_tile_width")
2153 "tilespec.normal_tile_height")) {
2154 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2155 goto ON_ERROR;
2156 }
2158 /* Adjust width to be multiple of 8 */
2159 if (scale != 1.0f) {
2160 i = t->normal_tile_width;
2161 while (i % 8 != 0) {
2162 i++;
2163 }
2164 t->scale = (t->scale * i) / t->normal_tile_width;
2165 t->normal_tile_width = i;
2166 }
2168 if (t->type == TS_ISOMETRIC) {
2170 if (tileset_hex_height(t) > 0) {
2172 } else {
2173 t->full_tile_height = 3 * t->normal_tile_height / 2;
2174 }
2175 } else {
2178 }
2180 = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
2182 = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
2184 "tilespec.small_tile_width")
2186 "tilespec.small_tile_height")) {
2187 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2188 goto ON_ERROR;
2189 }
2190 if (t->unit_tile_width != t->full_tile_width && t->scale != 1.0f) {
2192 }
2193 if (t->unit_tile_height != t->full_tile_height && t->scale != 1.0f) {
2195 }
2198 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
2202
2203 tstr = secfile_lookup_str(file, "tilespec.fog_style");
2204 if (tstr == nullptr) {
2205 log_error("Tileset \"%s\": no fog_style", t->name);
2206 goto ON_ERROR;
2207 }
2208
2210 if (!fog_style_is_valid(t->fogstyle)) {
2211 log_error("Tileset \"%s\": unknown fog_style \"%s\"", t->name, tstr);
2212 goto ON_ERROR;
2213 }
2214
2215 tstr = secfile_lookup_str(file, "tilespec.darkness_style");
2216 if (tstr == nullptr) {
2217 log_error("Tileset \"%s\": no darkness_style", t->name);
2218 goto ON_ERROR;
2219 }
2220
2223 log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t->name, tstr);
2224 goto ON_ERROR;
2225 }
2226
2228 && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
2229 log_error("Invalid darkness style set in tileset \"%s\".", t->name);
2230 goto ON_ERROR;
2231 }
2232
2234 "tilespec.unit_flag_offset_x")
2236 "tilespec.unit_flag_offset_y")
2238 "tilespec.city_flag_offset_x")
2240 "tilespec.city_flag_offset_y")
2241 || !secfile_lookup_int(file, &t->unit_offset_x,
2242 "tilespec.unit_offset_x")
2243 || !secfile_lookup_int(file, &t->unit_offset_y,
2244 "tilespec.unit_offset_y")
2246 "tilespec.activity_offset_x")
2248 "tilespec.activity_offset_y")
2249 || !secfile_lookup_int(file, &t->select_offset_x,
2250 "tilespec.select_offset_x")
2251 || !secfile_lookup_int(file, &t->select_offset_y,
2252 "tilespec.select_offset_y")
2254 "tilespec.stack_size_offset_x")
2256 "tilespec.stack_size_offset_y")
2257 || !secfile_lookup_int(file, &t->city_offset_x,
2258 "tilespec.city_offset_x")
2259 || !secfile_lookup_int(file, &t->city_offset_y,
2260 "tilespec.city_offset_y")
2262 "tilespec.city_size_offset_x")
2264 "tilespec.city_size_offset_y")
2266 "tilespec.citybar_offset_y")
2268 "tilespec.tilelabel_offset_y")
2270 "tilespec.occupied_offset_x")
2272 "tilespec.occupied_offset_y")) {
2273 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2274 goto ON_ERROR;
2275 }
2276
2278 "tilespec.unit_upkeep_offset_y");
2280 "tilespec.unit_upkeep_small_offset_y");
2281 t->svg_height = secfile_lookup_int_default(file, 44, "tilespec.svg_height");
2282 t->default_time_per_frame = secfile_lookup_int_default(file, 3, "tilespec.time_per_frame");
2283
2294 t->unit_offset_x = t->scale * t->unit_offset_x;
2295 t->unit_offset_y = t->scale * t->unit_offset_y;
2298 t->city_offset_x = t->scale * t->city_offset_x;
2299 t->city_offset_y = t->scale * t->city_offset_y;
2304 t->svg_height *= t->scale;
2305
2306 if (t->scale != 1.0f
2309 }
2310 if (t->scale != 1.0f
2313 }
2314
2315 c = secfile_lookup_str_default(file, nullptr,
2316 "tilespec.unit_default_orientation");
2317 if (!c) {
2318 /* This is valid, but tileset must specify icon for every unit */
2320 } else {
2321 dir = dir_by_tileset_name(c);
2322
2323 if (!direction8_is_valid(dir)) {
2325 _("Unknown unit_default_orientation \"%s\""), c);
2326 goto ON_ERROR;
2327 } else {
2328 /* Default orientation is allowed to not be a valid one for the
2329 * tileset */
2330 t->unit_default_orientation = dir;
2331 }
2332 }
2333
2334 c = secfile_lookup_str(file, "tilespec.main_intro_file");
2336 log_debug("intro file %s", t->main_intro_filename);
2337
2338 /* Layer order */
2339 num_layers = 0;
2340 layer_order = secfile_lookup_str_vec(file, &num_layers,
2341 "tilespec.layer_order");
2342 if (layer_order != nullptr) {
2343 for (i = 0; i < num_layers; i++) {
2344 int j;
2347
2348 /* Check for wrong layer names. */
2349 if (!mapview_layer_is_valid(layer)) {
2350 log_error("layer_order: Invalid layer \"%s\" in %s",
2352 goto ON_ERROR;
2353 }
2354 /* Check for duplicates. */
2355 for (j = 0; j < i; j++) {
2356 if (t->layer_order[j] == layer) {
2357 log_error("layer_order: Duplicate layer \"%s\" in %s",
2359 goto ON_ERROR;
2360 }
2361 }
2362 t->layer_order[i] = layer;
2363 }
2364
2365 /* Now check that all layers are present. Doing it now allows for a more
2366 * comprehensive error message. */
2367 for (i = 0; i < LAYER_COUNT; i++) {
2368 int j;
2369 bool found = FALSE;
2370
2371 for (j = 0; j < num_layers; j++) {
2372 if (i == t->layer_order[j]) {
2373 found = TRUE;
2374 break;
2375 }
2376 }
2377 if (!found) {
2378 log_error("layer_order: Missing layer \"%s\" in %s",
2380 goto ON_ERROR;
2381 }
2382 }
2383
2385 } else {
2386 /* There is no layer_order tag in the specfile -> use the default */
2387 for (i = 0; i < LAYER_COUNT; i++) {
2388 t->layer_order[i] = i;
2389 }
2390 }
2391
2392 /* Terrain layer info. */
2393 for (i = 0; i < MAX_NUM_LAYERS; i++) {
2394 struct tileset_layer *tslp = &t->layers[i];
2395 int j, k;
2396
2397 tslp->match_types =
2398 (char **) secfile_lookup_str_vec(file, &tslp->match_count,
2399 "layer%d.match_types", i);
2400 for (j = 0; j < tslp->match_count; j++) {
2401 tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
2402
2403 for (k = 0; k < j; k++) {
2404 if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
2406 _("[layer%d] match_types: \"%s\" initial "
2407 "('%c') is not unique."),
2408 i, tslp->match_types[j], tslp->match_types[j][0]);
2409 /* FIXME: Returns nullptr. */
2410 }
2411 }
2412 }
2413 }
2414
2415 /* Tile drawing info. */
2417 if (sections == nullptr || 0 == section_list_size(sections)) {
2419 _("No [%s] sections present."),
2421 goto ON_ERROR;
2422 }
2423
2424 fc_assert(t->tile_hash == nullptr);
2425
2427
2428 section_list_iterate(sections, psection) {
2429 const char *sec_name = section_name(psection);
2431 const char *sprite_type;
2432 int l;
2433 const char *terrain_name;
2434
2435 terrain_name = secfile_lookup_str(file, "%s.tag", sec_name);
2436
2437 if (terrain_name != nullptr) {
2438 draw->name = fc_strdup(terrain_name);
2439 } else {
2440 tileset_error(LOG_ERROR, _("No terrain tag given in section [%s] in %s."),
2443 goto ON_ERROR;
2444 }
2445
2446 draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
2447 sec_name);
2448 draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
2449
2450 draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
2451 "%s.is_reversed",
2452 sec_name);
2453 draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
2454 sec_name);
2455 draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
2456
2457 for (l = 0; l < draw->num_layers; l++) {
2458 struct drawing_layer *dlp = &draw->layer[l];
2459 struct tileset_layer *tslp = &t->layers[l];
2460 const char *match_type;
2461 const char **match_with;
2462 size_t count;
2463
2464 dlp->is_tall
2465 = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
2466 sec_name, l);
2467 dlp->offset_x
2468 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
2469 sec_name, l);
2470 dlp->offset_y
2471 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
2472 sec_name, l);
2473 dlp->offset_x = ceil(t->scale * dlp->offset_x);
2474 dlp->offset_y = ceil(t->scale * dlp->offset_y);
2475
2476 match_type = secfile_lookup_str_default(file, nullptr,
2477 "%s.layer%d_match_type",
2478 sec_name, l);
2479 if (match_type) {
2480 int j;
2481
2482 /* Determine our match_type. */
2483 for (j = 0; j < tslp->match_count; j++) {
2484 if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
2485 break;
2486 }
2487 }
2488 if (j >= tslp->match_count) {
2489 log_error("[%s] invalid match_type \"%s\" in %s.",
2491 } else {
2492 dlp->match_index[dlp->match_indices++] = j;
2493 }
2494 }
2495
2496 match_with = secfile_lookup_str_vec(file, &count,
2497 "%s.layer%d_match_with",
2498 sec_name, l);
2499 if (match_with) {
2500 int j, k;
2501
2502 if (count > MAX_NUM_MATCH_WITH) {
2503 log_error("[%s] match_with has too many types (%d, max %d) in %s",
2504 sec_name, (int) count, MAX_NUM_MATCH_WITH,
2505 tileset_name_get(t));
2506 count = MAX_NUM_MATCH_WITH;
2507 }
2508
2509 if (1 < dlp->match_indices) {
2510 log_error("[%s] previous match_with ignored in %s.",
2512 dlp->match_indices = 1;
2513 } else if (1 > dlp->match_indices) {
2514 log_error("[%s] missing match_type, using \"%s\" in %s.",
2515 sec_name, tslp->match_types[0], tileset_name_get(t));
2516 dlp->match_index[0] = 0;
2517 dlp->match_indices = 1;
2518 }
2519
2520 for (k = 0; k < count; k++) {
2521 for (j = 0; j < tslp->match_count; j++) {
2522 if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
2523 break;
2524 }
2525 }
2526 if (j >= tslp->match_count) {
2527 log_error("[%s] layer%d_match_with: invalid \"%s\".",
2528 sec_name, l, match_with[k]);
2529 } else if (1 < count) {
2530 int m;
2531
2532 for (m = 0; m < dlp->match_indices; m++) {
2533 if (dlp->match_index[m] == j) {
2534 log_error("[%s] layer%d_match_with: duplicate \"%s\" in %s.",
2536 break;
2537 }
2538 }
2539 if (m >= dlp->match_indices) {
2540 dlp->match_index[dlp->match_indices++] = j;
2541 }
2542 } else {
2543 dlp->match_index[dlp->match_indices++] = j;
2544 }
2545 }
2547 match_with = nullptr;
2548 }
2549
2550 /* Check match_indices */
2551 switch (dlp->match_indices) {
2552 case 0:
2553 case 1:
2554 dlp->match_style = MATCH_NONE;
2555 break;
2556 case 2:
2557 if (dlp->match_index[0] == dlp->match_index[1] ) {
2558 dlp->match_style = MATCH_SAME;
2559 } else {
2560 dlp->match_style = MATCH_PAIR;
2561 }
2562 break;
2563 default:
2564 dlp->match_style = MATCH_FULL;
2565 break;
2566 };
2567
2569 = secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
2570 sec_name, l);
2571 dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
2572
2573 switch (dlp->sprite_type) {
2574 case CELL_WHOLE:
2575 /* OK, no problem */
2576 break;
2577 case CELL_CORNER:
2578 if (dlp->is_tall
2579 || dlp->offset_x > 0
2580 || dlp->offset_y > 0) {
2581 log_error("[%s] layer %d: you cannot have tall terrain or\n"
2582 "a sprite offset with a cell-based drawing method in %s.",
2584 dlp->is_tall = FALSE;
2585 dlp->offset_x = dlp->offset_y = 0;
2586 }
2587 break;
2588 };
2589 }
2590
2591 if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
2592 log_error("warning: multiple tile sections containing terrain tag \"%s\" in %s.",
2593 draw->name, tileset_name_get(t));
2594 goto ON_ERROR;
2595 }
2597 section_list_destroy(sections);
2598 sections = nullptr;
2599
2601
2602 for (i = 0; i < ESTYLE_COUNT; i++) {
2604 }
2606
2607 for (i = 0; (extraname = secfile_lookup_str_default(file, nullptr,
2608 "extras.styles%d.name",
2609 i)); i++) {
2610 const char *style_name;
2611 enum extrastyle_id style;
2612
2613 style_name = secfile_lookup_str_default(file, "Single1",
2614 "extras.styles%d.style", i);
2616 if (!extrastyle_id_is_valid(style)) {
2617 log_error("Unknown extra style \"%s\" for extra \"%s\" in %s.",
2619 goto ON_ERROR;
2620 }
2621
2622 if (!estyle_hash_insert(t->estyle_hash, extraname, style)) {
2623 log_error("warning: duplicate extrastyle entry [%s] in %s.",
2625 goto ON_ERROR;
2626 }
2627 }
2628
2630
2633 "tilespec.files");
2634
2635 if (svg) {
2637 type_name = "svg";
2638
2639 /* Avoid "unused entry" warning about the other list */
2640 secfile_entry_ignore_by_path(file, "tilespec.files_pixel");
2641 } else {
2643 type_name = "pixel";
2644
2645 /* Avoid "unused entry" warning about the other list */
2646 secfile_entry_ignore_by_path(file, "tilespec.files_svg");
2647 }
2648
2651 "tilespec.files_%s", type_name);
2652 if ((spec_filenames[SFILE_COMMON] == nullptr
2654 && (spec_filenames[slist_type] == nullptr
2655 || num_spec_files[slist_type] == 0)) {
2656 log_error("No tile graphics files specified in \"%s\" for %s mode.",
2657 type_name, fname);
2658 goto ON_ERROR;
2659 }
2660
2661 fc_assert(t->sprite_hash == nullptr);
2663
2664 fc_assert(t->anim_hash == nullptr);
2665 t->anim_hash = anim_hash_new();
2666
2669 verbose, duplicates_ok)) {
2670 goto ON_ERROR;
2671 }
2672
2675 verbose, duplicates_ok)) {
2676 goto ON_ERROR;
2677 }
2678
2681
2683
2685 = (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2686 "tilespec.preferred_themes");
2687 t->num_preferred_themes = num_preferred_themes;
2688 for (i = 0; i < t->num_preferred_themes; i++) {
2690 }
2691
2693 secfile_destroy(file);
2694 log_verbose("Finished reading \"%s\".", fname);
2695 free(fname);
2696
2697 return t;
2698
2699ON_ERROR:
2700 secfile_destroy(file);
2701 free(fname);
2702 tileset_free(t);
2703
2704 if (sections != nullptr) {
2705 section_list_destroy(sections);
2706 }
2707
2708 return nullptr;
2709}
2710
2711/************************************************************************/
2714static const char *citizen_rule_name(enum citizen_category citizen)
2715{
2716 /* These strings are used in reading the tileset. Do not
2717 * translate. */
2718 switch (citizen) {
2719 case CITIZEN_HAPPY:
2720 return "happy";
2721 case CITIZEN_CONTENT:
2722 return "content";
2723 case CITIZEN_UNHAPPY:
2724 return "unhappy";
2725 case CITIZEN_ANGRY:
2726 return "angry";
2727 default:
2728 break;
2729 }
2730 log_error("Unknown citizen type: %d.", (int) citizen);
2731
2732 return nullptr;
2733}
2734
2735/************************************************************************/
2740static const char *cardinal_index_str(const struct tileset *t, int idx)
2741{
2742 static char c[64];
2743 int i;
2744
2745 c[0] = '\0';
2746 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2747 int value = (idx >> i) & 1;
2748
2749 cat_snprintf(c, sizeof(c), "%s%d",
2751 }
2752
2753 return c;
2754}
2755
2756/************************************************************************/
2760static char *valid_index_str(const struct tileset *t, int idx)
2761{
2762 static char c[64];
2763 int i;
2764
2765 c[0] = '\0';
2766 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2767 int value = (idx >> i) & 1;
2768
2769 cat_snprintf(c, sizeof(c), "%s%d",
2771 }
2772
2773 return c;
2774}
2775
2776/************************************************************************/
2783static struct anim *anim_new(int frames, int time_per_frame)
2784{
2785 struct anim *ret = fc_malloc(sizeof(struct anim));
2786
2787 ret->frames = frames;
2788 ret->time = -1;
2789 ret->time_per_frame = time_per_frame;
2790 ret->sprites = fc_malloc(frames * sizeof(struct sprite *));
2791 ret->show_always = FALSE;
2792
2793 return ret;
2794}
2795
2796/************************************************************************/
2801static void anim_free(struct anim *a)
2802{
2803 if (a != nullptr) {
2804 free(a->sprites);
2805 free(a);
2806 }
2807}
2808
2809/************************************************************************/
2816static struct sprite *load_sprite(struct tileset *t, const char *tag_name,
2817 bool scale, bool smooth, bool svgflag)
2818{
2819 struct small_sprite *ss;
2820 float sprite_scale = 1.0f;
2821
2822 log_debug("load_sprite(tag='%s')", tag_name);
2823 /* Lookup information about where the sprite is found. */
2825 return nullptr;
2826 }
2827
2828 fc_assert(ss->ref_count >= 0);
2829
2830 if (!ss->sprite) {
2831 /* If the sprite hasn't been loaded already, then load it. */
2832 fc_assert(ss->ref_count == 0);
2833
2834 if (ss->file) {
2835 int w, h;
2836 struct sprite *s;
2837
2838 if (scale) {
2839 s = load_gfx_file(ss->file, svgflag);
2840
2841 if (s != nullptr) {
2842 get_sprite_dimensions(s, &w, &h);
2843 ss->sprite = crop_sprite(s, 0, 0, w, h,
2844 nullptr, -1, -1, t->scale, smooth);
2845 free_sprite(s);
2846 }
2847 } else {
2848 ss->sprite = load_gfx_file(ss->file, svgflag);
2849 }
2850
2851 if (!ss->sprite) {
2853 _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2854 ss->file, tag_name);
2855 }
2856 } else {
2857 int sf_w, sf_h;
2858
2860 get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2861 if (ss->x < 0 || ss->x + ss->width > sf_w
2862 || ss->y < 0 || ss->y + ss->height > sf_h) {
2864 _("Sprite '%s' in file \"%s\" isn't within the image!"),
2865 tag_name, ss->sf->file_name);
2866 return nullptr;
2867 }
2868 if (scale) {
2869 sprite_scale = t->scale;
2870 }
2871 ss->sprite = crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width,
2872 ss->height, nullptr, -1, -1, sprite_scale,
2873 smooth);
2874 }
2875 }
2876
2877 /* Track the reference count so we know when to free the sprite. */
2878 ss->ref_count++;
2879
2880 return ss->sprite;
2881}
2882
2883/************************************************************************/
2886static struct sprite *create_plr_sprite(struct color *pcolor)
2887{
2888 struct sprite *sprite;
2889
2890 fc_assert_ret_val(pcolor != nullptr, nullptr);
2891
2894
2895 return sprite;
2896}
2897
2898/************************************************************************/
2902static void unload_sprite(struct tileset *t, const char *tag_name)
2903{
2904 struct small_sprite *ss;
2905
2908 fc_assert_ret(ss->ref_count >= 1);
2909 fc_assert_ret(ss->sprite);
2910
2911 ss->ref_count--;
2912
2913 if (ss->ref_count == 0) {
2914 /* Nobody's using the sprite anymore, so we should free it. We know
2915 * where to find it if we need it again. */
2916 log_debug("freeing sprite '%s'.", tag_name);
2917 free_sprite(ss->sprite);
2918 ss->sprite = nullptr;
2919 }
2920}
2921
2922/************************************************************************/
2926static bool sprite_exists(const struct tileset *t, const char *tag_name)
2927{
2928 /* Lookup information about where the sprite is found. */
2929 return sprite_hash_lookup(t->sprite_hash, tag_name, nullptr);
2930}
2931
2932/* Not very safe, but convenient: */
2933#define SET_SPRITE(field, tag) \
2934 do { \
2935 t->sprites.field = load_sprite(t, tag, TRUE, TRUE, FALSE); \
2936 if (t->sprites.field == nullptr) { \
2937 tileset_error(LOG_FATAL, tileset_name_get(t), \
2938 _("Sprite for tag '%s' missing."), tag); \
2939 } \
2940 } while (FALSE)
2941
2942
2943#define SET_SPRITE_NOTSMOOTH(field, tag) \
2944 do { \
2945 t->sprites.field = load_sprite(t, tag, TRUE, FALSE, FALSE); \
2946 if (t->sprites.field == nullptr) { \
2947 tileset_error(LOG_FATAL, tileset_name_get(t), \
2948 _("Sprite for tag '%s' missing."), tag); \
2949 } \
2950 } while (FALSE)
2951
2952#define SET_SPRITE_UNSCALED(field, tag) \
2953 do { \
2954 t->sprites.field = load_sprite(t, tag, FALSE, FALSE, FALSE); \
2955 if (t->sprites.field == nullptr) { \
2956 tileset_error(LOG_FATAL, tileset_name_get(t), \
2957 _("Sprite for tag '%s' missing."), tag); \
2958 } \
2959 } while (FALSE)
2960
2961/* Sets sprites.field to tag or (if tag isn't available) to alt */
2962#define SET_SPRITE_ALT(field, tag, alt) \
2963 do { \
2964 t->sprites.field = load_sprite(t, tag, TRUE, TRUE, FALSE); \
2965 if (!t->sprites.field) { \
2966 t->sprites.field = load_sprite(t, alt, TRUE, TRUE, FALSE); \
2967 } \
2968 if (t->sprites.field == nullptr) { \
2969 tileset_error(LOG_FATAL, tileset_name_get(t), \
2970 _("Sprite for tags '%s' and alternate '%s' are " \
2971 "both missing."), tag, alt); \
2972 } \
2973 } while (FALSE)
2974
2975/* Sets sprites.field to tag or (if tag isn't available) to deprecated alt */
2976#define SET_SPRITE_DEPR_ALT(field, tag, alt, ver) \
2977 do { \
2978 t->sprites.field = load_sprite(t, tag, TRUE, TRUE, FALSE); \
2979 if (!t->sprites.field) { \
2980 t->sprites.field = load_sprite(t, alt, TRUE, TRUE, FALSE); \
2981 if (t->sprites.field != nullptr) { \
2982 log_deprecation(_("%s: Using tag \"%s\" deprecated by \"%s\" in %s"), \
2983 tileset_name_get(t), alt, tag, ver); \
2984 } \
2985 } \
2986 if (t->sprites.field == nullptr) { \
2987 tileset_error(LOG_FATAL, tileset_name_get(t), \
2988 _("Sprite for tags '%s' and alternate '%s' are " \
2989 "both missing."), tag, alt); \
2990 } \
2991 } while (FALSE)
2992
2993/* Sets sprites.field to tag, or nullptr if not available */
2994#define SET_SPRITE_OPT(field, tag) \
2995 t->sprites.field = load_sprite(t, tag, TRUE, TRUE, FALSE)
2996
2997#define SET_SPRITE_ALT_OPT(field, tag, alt) \
2998 do { \
2999 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt, \
3000 nullptr, "sprite", \
3001 #field, TRUE); \
3002 } while (FALSE)
3003
3004#define SET_ANIM(field, tag) \
3005 do { \
3006 t->sprites.field = anim_load(t, tag, 0); \
3007 if (t->sprites.field == nullptr) { \
3008 tileset_error(LOG_FATAL, tileset_name_get(t), \
3009 _("Animation for tag '%s' missing."), tag); \
3010 } \
3011 } while (FALSE)
3012
3013/* Sets sprites.field to tag, or nullptr if not available */
3014#define SET_ANIM_OPT(field, tag) \
3015 t->sprites.field = anim_load(t, tag, 0)
3016
3017/************************************************************************/
3025static struct anim *anim_load(struct tileset *t, const char *tag,
3026 int time_per_frame)
3027{
3028 int frames = 0;
3029 char buf[1500];
3030 struct anim *ret;
3031 int i;
3032
3033 do {
3034 fc_snprintf(buf, sizeof(buf), "%s:%d", tag, frames++);
3035 } while (sprite_exists(t, buf));
3036
3037 if (--frames == 0) {
3038 return nullptr;
3039 }
3040
3041 if (time_per_frame <= 0) {
3043 }
3044
3046
3047 for (i = 0; i < frames; i++) {
3048 fc_snprintf(buf, sizeof(buf), "%s:%d", tag, i);
3049 ret->sprites[i] = load_sprite(t, buf, TRUE, TRUE, FALSE);
3050 if (ret->sprites[i] == nullptr) {
3052 _("Animation sprite for tag '%s' missing."), buf);
3053 }
3054 }
3055
3056 anim_hash_insert(t->anim_hash, tag, ret);
3057
3058 return ret;
3059}
3060
3061/************************************************************************/
3066static void anim_advance_time(struct anim *a)
3067{
3068 a->time++;
3069}
3070
3071/************************************************************************/
3077static struct sprite *anim_get_current_frame(struct anim *a)
3078{
3079 int time;
3080
3082 return a->sprites[0];
3083 }
3084
3085 if (a->time >= 0) {
3086 time = a->time;
3087 } else {
3088 time = global_anim_time;
3089 }
3090
3091 return a->sprites[(time / a->time_per_frame) % a->frames];
3092}
3093
3094/************************************************************************/
3099{
3101 nullptr, "default set", TRUE);
3102}
3103
3104/************************************************************************/
3108 struct citizen_set *set,
3110 const char *tag_group,
3111 const char *set_name,
3112 bool required)
3113{
3114 /* Load the specialist sprite graphics. */
3115 char buffer[512];
3116 int j;
3117 struct specialist *spe = specialist_by_number(id);
3118 const char *tag = spe->graphic_str;
3119 const char *graphic_alt = spe->graphic_alt;
3120
3121 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
3122 /* Try tag name + index number */
3123 if (tag_group != nullptr) {
3124 fc_snprintf(buffer, sizeof(buffer), "%s.%s_%d", tag_group, tag, j);
3125 } else {
3126 fc_snprintf(buffer, sizeof(buffer), "%s_%d", tag, j);
3127 }
3128 set->specialist[id].sprite[j] = load_sprite(t, buffer,
3129 FALSE, FALSE, FALSE);
3130
3131 /* Break if no more index specific sprites are defined */
3132 if (!set->specialist[id].sprite[j]) {
3133 break;
3134 }
3135 }
3136
3137 if (j == 0) {
3138 /* Try non-indexed */
3139 set->specialist[id].sprite[j] = load_sprite(t, tag,
3140 FALSE, FALSE, FALSE);
3141
3142 if (set->specialist[id].sprite[j]) {
3143 j = 1;
3144 }
3145 }
3146
3147 if (j == 0) {
3148 /* Try the alt tag */
3149 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
3150 /* Try alt tag name + index number */
3151 if (tag_group != nullptr) {
3152 fc_snprintf(buffer, sizeof(buffer), "%s.%s_%d",
3154 } else {
3155 fc_snprintf(buffer, sizeof(buffer), "%s_%d", graphic_alt, j);
3156 }
3157 set->specialist[id].sprite[j] = load_sprite(t, buffer,
3158 FALSE, FALSE, FALSE);
3159
3160 /* Break if no more index specific sprites are defined */
3161 if (!set->specialist[id].sprite[j]) {
3162 break;
3163 }
3164 }
3165 }
3166
3167 if (j == 0) {
3168 /* Try alt tag non-indexed */
3170 FALSE, FALSE, FALSE);
3171
3172 if (set->specialist[id].sprite[j]) {
3173 j = 1;
3174 }
3175 }
3176
3177 set->specialist[id].count = j;
3178
3179 /* Still nothing? Give up. */
3180 if (j == 0 && required) {
3181 /* TRANS: First %s is a graphics tag of the specialist, second one
3182 * is a citizen set name; 'citizen_graphic' from styles.ruleset */
3184 _("No graphics for specialist \"%s\" in %s."),
3185 tag, set_name);
3186 }
3187}
3188
3189/************************************************************************/
3193{
3195 "default set", TRUE);
3196}
3197
3198/************************************************************************/
3202 struct citizen_set *set,
3203 const char *tag_group,
3204 const char *set_name,
3205 bool required)
3206{
3207 int i, j;
3208 char buffer[512];
3209
3210 /* Load the citizen sprite graphics, no specialist. */
3211 for (i = 0; i < CITIZEN_LAST; i++) {
3212 const char *name = citizen_rule_name(i);
3213
3214 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
3215 if (tag_group != nullptr) {
3216 fc_snprintf(buffer, sizeof(buffer), "citizen.%s.%s_%d",
3217 tag_group, name, j);
3218 } else {
3219 fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
3220 }
3221 set->citizen[i].sprite[j] = load_sprite(t, buffer, FALSE, FALSE, FALSE);
3222 if (!set->citizen[i].sprite[j]) {
3223 break;
3224 }
3225 }
3226 set->citizen[i].count = j;
3227 if (j == 0 && required) {
3228 /* TRANS: First %s is type of the citizen ("happy" ... "angry"), second one
3229 * is a citizen set name; 'citizen_graphic' from styles.ruleset */
3231 _("No graphics for citizen \"%s\" in %s."),
3232 name, set_name);
3233 }
3234 }
3235}
3236
3237/************************************************************************/
3243static struct anim *get_city_anim(const struct city_sprite *city_sprite,
3244 const struct city *pcity)
3245{
3246 /* Get style and match the best tile based on city size */
3247 int style = style_of_city(pcity);
3248 int num_thresholds;
3250 int img_index;
3251
3252 fc_assert_ret_val(style < city_sprite->num_styles, nullptr);
3253
3256
3257 if (num_thresholds == 0) {
3258 return nullptr;
3259 }
3260
3261 /* Get the sprite with the index defined by the effects. */
3262 img_index = pcity->client.city_image;
3263 if (img_index == -100) {
3264 /* Server doesn't know right value as this is from old savegame.
3265 * Guess here based on *client* side information as was done in
3266 * versions where information was not saved to savegame - this should
3267 * give us right answer of what city looked like by the time it was
3268 * put under FoW. */
3270 }
3272
3273 return thresholds[img_index].cst;
3274}
3275
3276/************************************************************************/
3279static int load_city_thresholds_anims(struct tileset *t, const char *tag,
3280 char *graphic, char *graphic_alt,
3282{
3283 char buffer[128];
3284 char *gfx_in_use = graphic;
3285 int num_thresholds = 0;
3286 struct anim *anim;
3287 int size;
3288
3289 *thresholds = nullptr;
3290
3291 for (size = 0; size < MAX_CITY_SIZE; size++) {
3292 fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
3293 gfx_in_use, tag, size);
3294 if ((anim = anim_load(t, buffer, 0))) {
3297 (*thresholds)[num_thresholds - 1].cst = anim;
3298 } else if (size == 0) {
3299 if (gfx_in_use == graphic) {
3300 /* Try again with graphic_alt. */
3301 size--;
3302 gfx_in_use = graphic_alt;
3303 } else {
3304 /* Don't load any others if the 0 element isn't there. */
3305 break;
3306 }
3307 }
3308 }
3309
3310 return num_thresholds;
3311}
3312
3313/************************************************************************/
3320static struct city_sprite *load_city_sprite(struct tileset *t,
3321 const char *tag)
3322{
3323 struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
3324 int style;
3325
3326 /* Store number of styles we have allocated memory for.
3327 * game.control.num_city_styles might change if client disconnects from
3328 * server and connects new one. */
3331 * sizeof(*city_sprite->styles));
3332
3333 for (style = 0; style < city_sprite->num_styles; style++) {
3335 = load_city_thresholds_anims(t, tag, city_styles[style].graphic,
3336 city_styles[style].graphic_alt,
3338 }
3339
3340 return city_sprite;
3341}
3342
3343/************************************************************************/
3349{
3350 int style;
3351
3352 if (!city_sprite) {
3353 return;
3354 }
3355 for (style = 0; style < city_sprite->num_styles; style++) {
3356 if (city_sprite->styles[style].land_thresholds) {
3358 }
3359 }
3362}
3363
3364/************************************************************************/
3369{
3370 char buffer[512], buffer2[512];
3371 const int W = t->normal_tile_width, H = t->normal_tile_height;
3372 int i, j, f;
3373
3374 fc_assert_ret(t->sprite_hash != nullptr);
3375
3376 SET_SPRITE_UNSCALED(treaty_thumb[0], "treaty.disagree_thumb_down");
3377 SET_SPRITE_UNSCALED(treaty_thumb[1], "treaty.agree_thumb_up");
3378
3379 for (j = 0; j < INDICATOR_COUNT; j++) {
3380 const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
3381
3382 for (i = 0; i < NUM_TILES_PROGRESS; i++) {
3383 fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
3384 SET_SPRITE_UNSCALED(indicator[j][i], buffer);
3385 }
3386 }
3387
3388 SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
3389 SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
3390 SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
3391 if (t->type == TS_ISOMETRIC) {
3392 SET_SPRITE(dither_tile, "t.dither_tile");
3393 }
3394
3396 SET_SPRITE_NOTSMOOTH(mask.tile, "mask.tile");
3397 } else {
3398 SET_SPRITE(mask.tile, "mask.tile");
3399 }
3400 SET_SPRITE(mask.worked_tile, "mask.worked_tile");
3401 SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
3402
3403 SET_SPRITE_UNSCALED(tax_luxury, "s.tax_luxury");
3404 SET_SPRITE_UNSCALED(tax_science, "s.tax_science");
3405 SET_SPRITE_UNSCALED(tax_gold, "s.tax_gold");
3406
3408
3409 for (i = 0; i < SPACESHIP_COUNT; i++) {
3410 const char *names[SPACESHIP_COUNT]
3411 = {"solar_panels", "life_support", "habitation",
3412 "structural", "fuel", "propulsion", "exhaust"};
3413
3414 fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
3415 SET_SPRITE(spaceship[i], buffer);
3416 }
3417
3418 for (i = 0; i < CURSOR_LAST; i++) {
3419 const char *names[CURSOR_LAST] =
3420 {"goto", "patrol", "paradrop", "teleport", "nuke", "select",
3421 "invalid", "attack", "edit_paint", "edit_add", "wait"};
3422
3423 for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
3424 struct small_sprite *ss;
3425
3426 fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
3427 fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
3428 SET_SPRITE(cursor[i].frame[f], buffer);
3429
3430 if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
3431 t->sprites.cursor[i].hot_x = ss->hot_x;
3432 t->sprites.cursor[i].hot_y = ss->hot_y;
3433 }
3434 }
3435 }
3436
3437 for (i = 0; i < ICON_COUNT; i++) {
3438 const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
3439
3440 fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
3441 SET_SPRITE(icon[i], buffer);
3442 }
3443
3444 for (i = 0; i < E_COUNT; i++) {
3445 const char *tag = get_event_tag(i);
3446
3447 SET_SPRITE(events[i], tag);
3448 }
3449
3450 SET_SPRITE(explode.nuke, "explode.nuke");
3451
3453 for (i = 0; ; i++) {
3454 struct sprite *sprite;
3455
3456 fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
3457 sprite = load_sprite(t, buffer, TRUE, TRUE, FALSE);
3458 if (!sprite) {
3459 break;
3460 }
3462 }
3463
3464 SET_SPRITE(unit.auto_attack, "unit.auto_attack");
3465 /* TODO: Drop backward compatibility with "unit.auto_settler" tag. */
3466 SET_SPRITE_DEPR_ALT(unit.auto_worker, "unit.auto_worker", "unit.auto_settler", "3.3");
3467 SET_SPRITE(unit.auto_explore, "unit.auto_explore");
3468 SET_SPRITE(unit.fortified, "unit.fortified");
3469 SET_SPRITE(unit.fortifying, "unit.fortifying");
3470 SET_SPRITE(unit.go_to, "unit.goto");
3471 SET_SPRITE(unit.cultivate, "unit.cultivate");
3472 SET_SPRITE(unit.plant, "unit.plant");
3473 SET_SPRITE(unit.pillage, "unit.pillage");
3474 SET_SPRITE(unit.sentry, "unit.sentry");
3475 SET_SPRITE(unit.convert, "unit.convert");
3476 t->sprites.unit.stack = fc_malloc(sizeof(struct sprite *));
3477 t->sprites.unit.num_stack_sprites = 1;
3478 SET_SPRITE(unit.stack[0], "unit.stack");
3479 t->sprites.unit.no_more_stack_sprites = FALSE;
3480 SET_SPRITE(unit.loaded, "unit.loaded");
3481 SET_SPRITE(unit.transform, "unit.transform");
3482 SET_SPRITE(unit.connect, "unit.connect");
3483 SET_SPRITE(unit.patrol, "unit.patrol");
3484 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
3485 fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
3486 fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
3489 }
3490 SET_SPRITE(unit.lowfuel, "unit.lowfuel");
3491 SET_SPRITE(unit.tired, "unit.tired");
3492
3493 t->sprites.unit.action_decision_want = anim_load(t, "unit.action_decision_want",
3494 0);
3495
3496 for (i = 0; i < NUM_TILES_HP_BAR; i++) {
3497 fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
3498 SET_SPRITE(unit.hp_bar[i], buffer);
3499 }
3500
3501 for (i = 0; i < MAX_VET_LEVELS; i++) {
3502 /* Veteran level sprites are optional. For instance "green" units
3503 * usually have no special graphic. */
3504 fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
3505 t->sprites.unit.vet_lev[i] = load_sprite(t, buffer, TRUE, TRUE, FALSE);
3506 }
3507
3508 t->sprites.unit.select = anim_load(t, "unit.select", 1);
3509 if (t->sprites.unit.select != nullptr) {
3510 t->sprites.unit.select->show_always = TRUE;
3511 t->sprites.unit.select->time = 0; /* Not using global anim time */
3512 }
3513
3514 SET_SPRITE(citybar.shields, "citybar.shields");
3515 SET_SPRITE(citybar.food, "citybar.food");
3516 SET_SPRITE(citybar.trade, "citybar.trade");
3517 SET_SPRITE(citybar.occupied, "citybar.occupied");
3518 SET_SPRITE(citybar.background, "citybar.background");
3520 for (i = 0; ; i++) {
3521 struct sprite *sprite;
3522
3523 fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
3524 sprite = load_sprite(t, buffer, TRUE, TRUE, FALSE);
3525 if (!sprite) {
3526 break;
3527 }
3529 }
3530 if (t->sprites.citybar.occupancy.size < 2) {
3532 _("Missing necessary citybar.occupancy_N sprites."));
3533 }
3534
3535#define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
3536 SET_EDITOR_SPRITE(erase);
3537 SET_EDITOR_SPRITE(brush);
3538 SET_EDITOR_SPRITE(copy);
3539 SET_EDITOR_SPRITE(paste);
3540 SET_EDITOR_SPRITE(copypaste);
3543 SET_EDITOR_SPRITE(terrain_resource);
3544 SET_EDITOR_SPRITE(terrain_special);
3548 SET_EDITOR_SPRITE(territory);
3549 SET_EDITOR_SPRITE(properties);
3551 SET_EDITOR_SPRITE(military_base);
3552#undef SET_EDITOR_SPRITE
3553
3554 SET_SPRITE(city.disorder, "city.disorder");
3555
3556 /* Fallbacks for goto path turn numbers:
3557 * path.step_%d, path.exhausted_mp_%d
3558 * --> path.turns_%d
3559 * --> city.size_%d */
3560#define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name) \
3561 fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
3562 SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer); \
3563 if (t->sprites.path.s[state].turns ## factor_name [i] == nullptr) { \
3564 t->sprites.path.s[state].turns ## factor_name [i] = \
3565 t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i]; \
3566 }
3567
3568 for (i = 0; i < NUM_TILES_DIGITS; i++) {
3569 fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
3570 SET_SPRITE(city.size[i], buffer);
3571 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
3572 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns[i], buffer2, buffer);
3574 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp",,);
3575
3576 fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
3577 SET_SPRITE(city.size_tens[i], buffer);
3578 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
3579 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns_tens[i], buffer2, buffer);
3581 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 0, _tens);
3582
3583 fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
3584 SET_SPRITE_OPT(city.size_hundreds[i], buffer);
3585 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
3586 SET_SPRITE_ALT_OPT(path.s[GTS_MP_LEFT].turns_hundreds[i], buffer2,
3587 buffer);
3589 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 00, _hundreds);
3590
3591 fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
3592 SET_SPRITE(city.tile_foodnum[i], buffer);
3593 fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
3594 SET_SPRITE(city.tile_shieldnum[i], buffer);
3595 fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
3596 SET_SPRITE(city.tile_tradenum[i], buffer);
3597 }
3598#undef SET_GOTO_TURN_SPRITE
3599
3600 /* Must have at least one upkeep sprite per output type (and unhappy) */
3601 /* The rest are optional; we copy the previous sprite for unspecified ones */
3602 fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
3603 SET_SPRITE(upkeep.unhappy[0], buffer);
3604 for (i = 1; i < MAX_NUM_UPKEEP_SPRITES; i++) {
3605 fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
3606 if (sprite_exists(t, buffer2)) {
3607 SET_SPRITE(upkeep.unhappy[i], buffer2);
3608 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3609 } else {
3610 SET_SPRITE(upkeep.unhappy[i], buffer);
3611 }
3612 }
3614 fc_snprintf(buffer, sizeof(buffer),
3615 "upkeep.%s", get_output_identifier(o));
3616 SET_SPRITE_OPT(upkeep.output[o][0], buffer);
3617 for (i = 1; i < MAX_NUM_UPKEEP_SPRITES; i++) {
3618 fc_snprintf(buffer2, sizeof(buffer2),
3619 "upkeep.%s%d", get_output_identifier(o), i+1);
3620 if (sprite_exists(t, buffer2)) {
3621 SET_SPRITE(upkeep.output[o][i], buffer2);
3622 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3623 } else {
3624 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
3625 SET_SPRITE_OPT(upkeep.output[o][i], buffer);
3626 }
3627 }
3629
3631
3632 SET_SPRITE(user.attention, "user.attention");
3633 SET_SPRITE(user.infratile, "user.infratile");
3634
3635 SET_SPRITE_OPT(path.s[GTS_MP_LEFT].specific, "path.normal");
3636 SET_SPRITE_OPT(path.s[GTS_EXHAUSTED_MP].specific, "path.exhausted_mp");
3637 SET_SPRITE_OPT(path.s[GTS_TURN_STEP].specific, "path.step");
3638 SET_SPRITE(path.waypoint, "path.waypoint");
3639
3640 SET_SPRITE_NOTSMOOTH(tx.fog, "tx.fog");
3641
3643 for (i = 0; ; i++) {
3644 struct sprite *sprite;
3645
3646 fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
3647 sprite = load_sprite(t, buffer, TRUE, TRUE, FALSE);
3648 if (!sprite) {
3649 break;
3650 }
3652 }
3653 if (i == 0) {
3655 _("Missing overlay-color sprite colors.overlay_0."));
3656 }
3657
3658 /* Chop up and build the overlay graphics. */
3663 for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
3664 struct sprite *color, *color_mask;
3665 struct sprite *worked, *unworked;
3666
3668 color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0,
3669 1.0f, FALSE);
3670 worked = crop_sprite(color_mask, 0, 0, W, H,
3671 t->sprites.mask.worked_tile, 0, 0, 1.0f, FALSE);
3672 unworked = crop_sprite(color_mask, 0, 0, W, H,
3673 t->sprites.mask.unworked_tile, 0, 0, 1.0f, FALSE);
3675 t->sprites.city.worked_tile_overlay.p[i] = worked;
3677 }
3678
3679
3680 {
3681 SET_SPRITE(grid.unavailable, "grid.unavailable");
3682 SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
3683
3684 for (i = 0; i < EDGE_COUNT; i++) {
3685 int be;
3686
3687 if (i == EDGE_UD && t->hex_width == 0) {
3688 continue;
3689 } else if (i == EDGE_LR && t->hex_height == 0) {
3690 continue;
3691 }
3692
3693 fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
3694 SET_SPRITE(grid.main[i], buffer);
3695
3696 fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
3697 SET_SPRITE(grid.city[i], buffer);
3698
3699 fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
3700 SET_SPRITE(grid.worked[i], buffer);
3701
3702 fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
3703 SET_SPRITE(grid.selected[i], buffer);
3704
3705 fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
3706 SET_SPRITE(grid.coastline[i], buffer);
3707
3708 for (be = 0; be < 2; be++) {
3709 fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
3710 edge_name[i][be]);
3711 SET_SPRITE(grid.borders[i][be], buffer);
3712 }
3713 }
3714 }
3715
3716 switch (t->darkness_style) {
3717 case DARKNESS_NONE:
3718 /* Nothing. */
3719 break;
3720 case DARKNESS_ISORECT:
3721 {
3722 /* Isometric: take a single tx.darkness tile and split it into 4. */
3723 struct sprite *darkness = load_sprite(t, "tx.darkness",
3724 TRUE, FALSE, FALSE);
3725 const int ntw = t->normal_tile_width, nth = t->normal_tile_height;
3726 int offsets[4][2] = {{ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
3727
3728 if (!darkness) {
3730 _("Sprite tx.darkness missing."));
3731 }
3732 for (i = 0; i < 4; i++) {
3733 t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
3734 offsets[i][1], ntw / 2,
3735 nth / 2, nullptr, 0, 0, 1.0f,
3736 FALSE);
3737 }
3738 }
3739 break;
3741 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3742 enum direction8 dir = t->cardinal_tileset_dirs[i];
3743
3744 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3746 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3747 }
3748 break;
3749 case DARKNESS_CARD_FULL:
3750 for (i = 1; i < t->num_index_cardinal; i++) {
3751 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3752 cardinal_index_str(t, i));
3753 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3754 }
3755 break;
3756 case DARKNESS_CORNER:
3758 81 * sizeof(*t->sprites.tx.fullfog));
3759 for (i = 0; i < 81; i++) {
3760 /* Unknown, fog, known. */
3761 char ids[] = {'u', 'f', 'k'};
3762 char buf[512] = "t.fog";
3763 int values[4], vi, k = i;
3764
3765 for (vi = 0; vi < 4; vi++) {
3766 values[vi] = k % 3;
3767 k /= 3;
3768
3769 cat_snprintf(buf, sizeof(buf), "_%c", ids[values[vi]]);
3770 }
3771 fc_assert(k == 0);
3772
3774 }
3775 break;
3776 };
3777
3778 /* No other place to initialize these variables */
3781}
3782
3783/************************************************************************/
3786static bool load_river_sprites(struct tileset *t,
3787 struct river_sprites *store, const char *tag_pfx)
3788{
3789 int i;
3790 char buffer[512];
3791
3792 for (i = 0; i < t->num_index_cardinal; i++) {
3793 fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
3795 store->spec[i] = anim_load(t, buffer, 0);
3796 if (store->spec[i] == nullptr) {
3797 return FALSE;
3798 }
3799 }
3800
3801 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3802 fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%s",
3804 store->outlet[i] = anim_load(t, buffer, 0);
3805 if (store->outlet[i] == nullptr) {
3806 log_error("Missing \"%s\" for \"%s\".", buffer, tag_pfx);
3807 return FALSE;
3808 }
3809 }
3810
3811 return TRUE;
3812}
3813
3814/************************************************************************/
3821{
3823 if (sf->big_sprite) {
3824 free_sprite(sf->big_sprite);
3825 sf->big_sprite = nullptr;
3826 }
3828}
3829
3830/************************************************************************/
3841
3842/************************************************************************/
3848 enum log_level level,
3849 const char *tag, const char *alt,
3850 const char *alt2,
3851 const char *what, const char *name,
3852 bool scale)
3853{
3854 struct sprite *sp;
3855
3856 /* (Should get sprite_hash before connection) */
3857 fc_assert_ret_val_msg(t->sprite_hash != nullptr, nullptr,
3858 "attempt to lookup for %s \"%s\" before "
3859 "sprite_hash setup", what, name);
3860
3861 sp = load_sprite(t, tag, scale, TRUE, FALSE);
3862 if (sp) return sp;
3863
3864 sp = load_sprite(t, alt, scale, TRUE, FALSE);
3865 if (sp) {
3866 log_verbose("Using alternate graphic \"%s\" "
3867 "(instead of \"%s\") for %s \"%s\".",
3868 alt, tag, what, name);
3869 return sp;
3870 }
3871
3872 if (alt2 != nullptr) {
3873 sp = load_sprite(t, alt2, scale, TRUE, FALSE);
3874 if (sp) {
3875 log_verbose("Using second alternate graphic \"%s\" "
3876 "(instead of \"%s\" or \"%s\") for %s \"%s\".",
3877 alt2, tag, alt, what, name);
3878 return sp;
3879 }
3880 }
3881
3883 _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3884 tag, alt, what, name);
3885
3886 return nullptr;
3887}
3888
3889/************************************************************************/
3894 int uidx,
3895 const char *base_str,
3896 enum direction8 dir,
3897 enum unit_activity activity,
3898 bool has_icon)
3899{
3900 enum direction8 loaddir = dir;
3901 char buf[2048];
3902 const char *act_name = unit_activity_name(activity);
3903
3904 if (act_name == nullptr) {
3905 /* gcc-9 thinks this is possible. */
3906 return FALSE;
3907 }
3908
3909 /*
3910 * There may be more orientations available in this tileset than are
3911 * needed, if an oriented unit set has been reused between tilesets.
3912 *
3913 * Don't bother loading unused ones, unless they might be used by
3914 * unit_default_orientation (logic here mirrors get_unittype_sprite()).
3915 */
3916 if (!(dir == t->unit_default_orientation && !has_icon)
3917 && !is_valid_tileset_dir(t, dir)) {
3918 /* Instead we copy a nearby valid dir's sprite, so we're not caught
3919 * out in case this tileset is used with an incompatible topology,
3920 * although it'll be ugly. */
3921 do {
3923 /* This loop _should_ terminate... */
3925 } while (!is_valid_tileset_dir(t, loaddir));
3926 }
3927
3928 fc_snprintf(buf, sizeof(buf), "%s_%s_%s", base_str,
3930
3931 /* We don't use _alt graphics here, as that could lead to loading
3932 * real icon gfx, but alternative orientation gfx. Tileset author
3933 * probably meant icon gfx to be used as fallback for all orientations */
3934 t->sprites.units.facing[uidx][dir][activity] = anim_load(t, buf, 0);
3935
3936 if (activity == ACTIVITY_IDLE
3937 && t->sprites.units.facing[uidx][dir][activity] == nullptr) {
3938 /* Backward compatibility: Set Idle sprite from tag with no activity defined. */
3939 fc_snprintf(buf, sizeof(buf), "%s_%s", base_str,
3941
3942 t->sprites.units.facing[uidx][dir][activity] = anim_load(t, buf, 0);
3943 }
3944
3945 if (t->sprites.units.facing[uidx][dir][activity] != nullptr) {
3946 return TRUE;
3947 }
3948
3949 return FALSE;
3950}
3951
3952/************************************************************************/
3956 int uidx,
3957 const char *tag)
3958{
3960
3961 activity_type_iterate(activity) {
3962 char buffer[2048];
3963
3964 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3965 tag, unit_activity_name(activity));
3966 t->sprites.units.icon[uidx][activity] = anim_load(t, buffer, 0);
3967
3968 if (activity == ACTIVITY_IDLE
3969 && t->sprites.units.icon[uidx][activity] == nullptr) {
3970 /* Backward compatibility: Set Idle sprite from tag with no activity defined. */
3971 t->sprites.units.icon[uidx][activity] = anim_load(t, tag, 0);
3972 }
3974
3975 has_icon = t->sprites.units.icon[uidx][ACTIVITY_IDLE] != nullptr;
3976
3977#define LOAD_FACING_SPRITE(dir) \
3978 if (!tileset_setup_unit_direction(t, uidx, tag, dir, activity, has_icon)) { \
3979 facing_sprites[activity] = FALSE; \
3980 }
3981
3982 activity_type_iterate(activity) {
3983 facing_sprites[activity] = TRUE;
3984
3993
3995
3997 /* Neither icon gfx or orientation sprites */
3998 return FALSE;
3999 }
4000
4001 return TRUE;
4002
4003#undef LOAD_FACING_SPRITE
4004}
4005
4006/************************************************************************/
4011{
4012 int uidx = utype_index(ut);
4013
4014 if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
4015 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)
4016 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt2)) {
4018 _("Missing %s unit sprites for tags \"%s\" and alternatives "
4019 "\"%s\" and \"%s\"."),
4020 utype_rule_name(ut), ut->graphic_str,
4021 ut->graphic_alt, ut->graphic_alt2);
4022 }
4023
4024 if (!t->sprites.units.icon[uidx][ACTIVITY_IDLE]) {
4027 _("Unit type %s has no unoriented sprites and "
4028 "tileset has no unit_default_orientation."),
4030 } else {
4031 /* We're guaranteed to have an oriented sprite corresponding to
4032 * unit_default_orientation, because tileset_setup_unit_type_from_tag()
4033 * checked for this. */
4035 != nullptr);
4036 }
4037 }
4038}
4039
4040/************************************************************************/
4045 struct impr_type *pimprove)
4046{
4047 t->sprites.building[improvement_index(pimprove)]
4049 pimprove->graphic_alt, pimprove->graphic_alt2,
4050 "improvement",
4051 improvement_rule_name(pimprove), FALSE);
4052
4053 /* Should maybe do something if nullptr, eg generic default? */
4054}
4055
4056/************************************************************************/
4061 struct advance *padvance)
4062{
4063 if (valid_advance(padvance)) {
4066 padvance->graphic_alt, nullptr,
4067 "technology",
4069
4070 /* Should maybe do something if nullptr, eg generic default? */
4071 } else {
4072 t->sprites.tech[advance_index(padvance)] = nullptr;
4073 }
4074}
4075
4076/************************************************************************/
4081 struct extra_type *pextra)
4082{
4083 const int id = extra_index(pextra);
4084 enum extrastyle_id extrastyle;
4085
4086 if (!fc_strcasecmp(pextra->graphic_str, "none")) {
4087 /* Extra without graphics */
4089 } else {
4090 const char *tag;
4091
4092 tag = pextra->graphic_str;
4093 if (!estyle_hash_lookup(t->estyle_hash, tag, &extrastyle)) {
4094 tag = pextra->graphic_alt;
4095 if (!estyle_hash_lookup(t->estyle_hash, tag, &extrastyle)) {
4097 _("No extra style for \"%s\" or \"%s\"."),
4098 pextra->graphic_str,
4099 pextra->graphic_alt);
4100 } else {
4101 log_verbose("Using alternate graphic \"%s\" "
4102 "(instead of \"%s\") for extra \"%s\".",
4103 pextra->graphic_alt, pextra->graphic_str,
4104 extra_rule_name(pextra));
4105 }
4106 }
4107
4108 t->sprites.extras[id].extrastyle = extrastyle;
4109
4110 extra_type_list_append(t->style_lists[extrastyle], pextra);
4111
4112 if (extra_has_flag(pextra, EF_SHOW_FLAG)) {
4114 }
4115
4116 switch (extrastyle) {
4117 case ESTYLE_3LAYER:
4118 tileset_setup_base(t, pextra, tag);
4119 break;
4120
4124 case ESTYLE_RIVER:
4125 tileset_setup_road(t, pextra, tag);
4126 break;
4127
4128 case ESTYLE_SINGLE1:
4129 case ESTYLE_SINGLE2:
4130 SET_ANIM(extras[id].u.single, tag);
4131 break;
4132
4133 case ESTYLE_CARDINALS:
4134 {
4135 int i;
4136 char buffer[512];
4137
4138 /* We use direction-specific irrigation and farmland graphics, if they
4139 * are available. If not, we just fall back to the basic irrigation
4140 * graphics. */
4141 for (i = 0; i < t->num_index_cardinal; i++) {
4142 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
4143 tag, cardinal_index_str(t, i));
4144 t->sprites.extras[id].u.cardinals[i] = anim_load(t, buffer, 0);
4145 if (t->sprites.extras[id].u.cardinals[i] == nullptr) {
4146 t->sprites.extras[id].u.cardinals[i] = anim_load(t, tag, 0);
4147 }
4148 if (t->sprites.extras[id].u.cardinals[i] == nullptr) {
4150 _("No cardinal-style graphics \"%s*\" for "
4151 "extra \"%s\""),
4152 tag, extra_rule_name(pextra));
4153 }
4154 }
4155 }
4156 break;
4157 case ESTYLE_COUNT:
4158 break;
4159 }
4160 }
4161
4162 if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
4163 t->sprites.extras[id].activity = nullptr;
4164 } else {
4166 TRUE, TRUE, FALSE);
4167 if (t->sprites.extras[id].activity == nullptr) {
4169 TRUE, TRUE, FALSE);
4170 }
4171 if (t->sprites.extras[id].activity == nullptr) {
4173 TRUE, TRUE, FALSE);
4174 }
4175 if (t->sprites.extras[id].activity == nullptr) {
4177 _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
4178 extra_rule_name(pextra), pextra->activity_gfx,
4179 pextra->act_gfx_alt, pextra->act_gfx_alt2);
4180 }
4181 }
4182
4183 if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
4184 t->sprites.extras[id].rmact = nullptr;
4185 } else {
4186 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx,
4187 TRUE, TRUE, FALSE);
4188 if (t->sprites.extras[id].rmact == nullptr) {
4190 TRUE, TRUE, FALSE);
4191 if (t->sprites.extras[id].rmact == nullptr) {
4193 TRUE, TRUE, FALSE);
4194 if (t->sprites.extras[id].rmact == nullptr) {
4196 _("Missing %s removal activity sprite for tags \"%s\" "
4197 "and alternatives \"%s\" and \"%s\"."),
4198 extra_rule_name(pextra), pextra->rmact_gfx,
4199 pextra->rmact_gfx_alt, pextra->rmact_gfx_alt2);
4200 }
4201 }
4202 }
4203 }
4204}
4205
4206/************************************************************************/
4210static void tileset_setup_road(struct tileset *t,
4211 struct extra_type *pextra,
4212 const char *tag)
4213{
4214 char full_tag_name[MAX_LEN_NAME + sizeof("_isolated")];
4215 const int id = extra_index(pextra);
4216 int i;
4217 enum extrastyle_id extrastyle = t->sprites.extras[id].extrastyle;
4218
4219 /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
4220 ESTYLE_ROAD_PARITY_COMBINED. */
4221 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4222 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4224 "%s_isolated", tag);
4225
4226 SET_ANIM(extras[id].u.road.isolated, full_tag_name);
4227 }
4228
4229 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
4230 /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each
4231 * road type: one going off in each direction. */
4232 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4233 enum direction8 dir = t->valid_tileset_dirs[i];
4234 const char *dir_name = dir_get_tileset_name(dir);
4235
4237 "%s_%s", tag, dir_name);
4238
4239 SET_ANIM(extras[id].u.road.ru.dir[i], full_tag_name);
4240 }
4241 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4242 int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
4243
4244 /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road
4245 * type: 16 each for cardinal and diagonal directions. Each set
4246 * of 16 provides a NSEW-indexed sprite to provide connectors for
4247 * all rails in the cardinal/diagonal directions. The 0 entry is
4248 * unused (the "isolated" sprite is used instead). */
4249
4250 for (i = 1; i < num_index; i++) {
4251 char c[64] = "", d[64] = "";
4252
4253 for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
4254 int value = (i >> j) & 1;
4255
4256 cat_snprintf(c, sizeof(c), "%s%d",
4258 value);
4259 cat_snprintf(d, sizeof(d), "%s%d",
4261 value);
4262 }
4263
4265 "%s_c_%s", tag, c);
4266
4267 SET_ANIM(extras[id].u.road.ru.combo.even[i], full_tag_name);
4268
4270 "%s_d_%s", tag, d);
4271
4272 SET_ANIM(extras[id].u.road.ru.combo.odd[i], full_tag_name);
4273 }
4274 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4275 /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
4276 * Just go around clockwise, with all combinations. */
4277 for (i = 0; i < t->num_index_valid; i++) {
4278 char *idx_str = valid_index_str(t, i);
4279
4281 "%s_%s", tag, idx_str);
4282
4283 SET_ANIM(extras[id].u.road.ru.total[i], full_tag_name);
4284 }
4285 } else if (extrastyle == ESTYLE_RIVER) {
4286 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers, tag)) {
4288 _("No river-style graphics \"%s*\" for extra \"%s\""),
4289 tag, extra_rule_name(pextra));
4290 }
4291 } else {
4293 }
4294
4295 /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE,
4296 * ESTYLE_ROAD_PARITY_COMBINED and ESTYLE_ROAD_ALL_COMBINED. */
4297 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4298 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED
4299 || extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4300 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4301 enum direction8 dir = t->valid_tileset_dirs[i];
4302
4303 if (!is_cardinal_tileset_dir(t, dir)) {
4304 const char *dtn = dir_get_tileset_name(dir);
4305
4307 "%s_c_%s", pextra->graphic_str, dtn);
4308
4309 SET_ANIM_OPT(extras[id].u.road.corner[dir], full_tag_name);
4310 }
4311 }
4312 }
4313}
4314
4315/************************************************************************/
4319static void tileset_setup_base(struct tileset *t,
4320 const struct extra_type *pextra,
4321 const char *tag)
4322{
4323 char full_tag_name[MAX_LEN_NAME + sizeof("_fg")];
4324 const int id = extra_index(pextra);
4325
4326 fc_assert_ret(id >= 0 && id < extra_count());
4327
4329 strcat(full_tag_name, "_bg");
4331
4333 strcat(full_tag_name, "_mg");
4335
4337 strcat(full_tag_name, "_fg");
4339
4340 if (t->sprites.extras[id].u.bmf.background == nullptr
4341 && t->sprites.extras[id].u.bmf.middleground == nullptr
4342 && t->sprites.extras[id].u.bmf.foreground == nullptr) {
4343 /* There was an extra style definition but no matching graphics */
4345 _("No graphics with tag \"%s_bg/mg/fg\" for extra \"%s\""),
4346 tag, extra_rule_name(pextra));
4347 }
4348}
4349
4350/************************************************************************/
4355 const struct terrain *pterrain)
4356{
4357 struct drawing_data *draw;
4358 struct sprite *sprite;
4359 char buffer[MAX_LEN_NAME + 20];
4360 int i, l;
4361
4362 if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
4363 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)
4364 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt2, &draw)) {
4366 _("Terrain \"%s\": no graphic tile \"%s\", \"%s\", or \"%s\"."),
4367 terrain_rule_name(pterrain), pterrain->graphic_str,
4368 pterrain->graphic_alt, pterrain->graphic_alt2);
4369 }
4370
4371 if (draw->init) {
4372 t->sprites.drawing[terrain_index(pterrain)] = draw;
4373 return;
4374 }
4375
4376 /* Set up each layer of the drawing. */
4377 for (l = 0; l < draw->num_layers; l++) {
4378 struct drawing_layer *dlp = &draw->layer[l];
4379 struct tileset_layer *tslp = &t->layers[l];
4380 sprite_vector_init(&dlp->base);
4381 sprite_vector_init(&dlp->allocated);
4382
4383 switch (dlp->sprite_type) {
4384 case CELL_WHOLE:
4385 switch (dlp->match_style) {
4386 case MATCH_NONE:
4387 /* Load whole sprites for this tile. */
4388 for (i = 0; ; i++) {
4389 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
4390 l, draw->name, i + 1);
4391 sprite = load_sprite(t, buffer, TRUE, FALSE, FALSE);
4392 if (!sprite) {
4393 break;
4394 }
4395 sprite_vector_reserve(&dlp->base, i + 1);
4396 dlp->base.p[i] = sprite;
4397 }
4398 /* Check for base sprite, allowing missing sprites above base */
4399 if (0 == i && 0 == l) {
4400 /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
4402 _("Missing base sprite for tag \"%s\"."), buffer);
4403 }
4404 break;
4405 case MATCH_SAME:
4406 /* Load 16 cardinally-matched sprites. */
4407 for (i = 0; i < t->num_index_cardinal; i++) {
4408 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
4409 l, draw->name, cardinal_index_str(t, i));
4410 dlp->match[i]
4411 = tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4412 nullptr, "matched terrain",
4413 terrain_rule_name(pterrain), TRUE);
4414 }
4415 break;
4416 case MATCH_PAIR:
4417 case MATCH_FULL:
4418 fc_assert(FALSE); /* Not yet defined */
4419 break;
4420 };
4421 break;
4422 case CELL_CORNER:
4423 {
4424 const int count = dlp->match_indices;
4425 int number = NUM_CORNER_DIRS;
4426
4427 switch (dlp->match_style) {
4428 case MATCH_NONE:
4429 /* Do nothing */
4430 break;
4431 case MATCH_PAIR:
4432 case MATCH_SAME:
4433 /* N directions (NSEW) * 3 dimensions of matching */
4434 fc_assert(count == 2);
4435 number = NUM_CORNER_DIRS * 2 * 2 * 2;
4436 break;
4437 case MATCH_FULL:
4438 default:
4439 /* N directions (NSEW) * 3 dimensions of matching */
4440 /* could use exp() or expi() here? */
4441 number = NUM_CORNER_DIRS * count * count * count;
4442 break;
4443 };
4444
4445 dlp->cells
4446 = fc_calloc(number, sizeof(*dlp->cells));
4447
4448 for (i = 0; i < number; i++) {
4449 enum direction4 dir = i % NUM_CORNER_DIRS;
4450 int value = i / NUM_CORNER_DIRS;
4451
4452 switch (dlp->match_style) {
4453 case MATCH_NONE:
4454 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
4455 l, draw->name, direction4letters[dir]);
4456 dlp->cells[i]
4457 = tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4458 nullptr, "cell terrain",
4459 terrain_rule_name(pterrain), TRUE);
4460 break;
4461 case MATCH_SAME:
4462 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
4463 l, draw->name, direction4letters[dir],
4464 (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
4465 dlp->cells[i]
4466 = tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4467 nullptr, "same cell terrain",
4468 terrain_rule_name(pterrain), TRUE);
4469 break;
4470 case MATCH_PAIR:
4471 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
4472 l, draw->name, direction4letters[dir],
4473 tslp->match_types[dlp->match_index[(value) & 1]][0],
4474 tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
4475 tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
4476 dlp->cells[i]
4477 = tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4478 nullptr, "cell pair terrain",
4479 terrain_rule_name(pterrain), TRUE);
4480 break;
4481 case MATCH_FULL:
4482 {
4483 int this = dlp->match_index[0];
4484 int n, s, e, w;
4485 int v1, v2, v3;
4486
4487 v1 = dlp->match_index[value % count];
4488 value /= count;
4489 v2 = dlp->match_index[value % count];
4490 value /= count;
4491 v3 = dlp->match_index[value % count];
4492
4493 fc_assert(v1 < count && v2 < count && v3 < count);
4494
4495 /* Assume merged cells. This should be a separate option. */
4496 switch (dir) {
4497 case DIR4_NORTH:
4498 s = this;
4499 w = v1;
4500 n = v2;
4501 e = v3;
4502 break;
4503 case DIR4_EAST:
4504 w = this;
4505 n = v1;
4506 e = v2;
4507 s = v3;
4508 break;
4509 case DIR4_SOUTH:
4510 n = this;
4511 e = v1;
4512 s = v2;
4513 w = v3;
4514 break;
4515 case DIR4_WEST:
4516 default: /* Avoid warnings */
4517 e = this;
4518 s = v1;
4519 w = v2;
4520 n = v3;
4521 break;
4522 };
4523
4524 /* Use first character of match_types,
4525 * already checked for uniqueness. */
4526 fc_snprintf(buffer, sizeof(buffer),
4527 "t.l%d.cellgroup_%c_%c_%c_%c", l,
4528 tslp->match_types[n][0], tslp->match_types[e][0],
4529 tslp->match_types[s][0], tslp->match_types[w][0]);
4530 sprite = load_sprite(t, buffer, TRUE, FALSE, FALSE);
4531
4532 if (sprite) {
4533 /* Crop the sprite to separate this cell. */
4534 int vec_size = sprite_vector_size(&dlp->allocated);
4535
4536 const int W = t->normal_tile_width;
4537 const int H = t->normal_tile_height;
4538 int x[4] = {W / 4, W / 4, 0, W / 2};
4539 int y[4] = {H / 2, 0, H / 4, H / 4};
4540 int xo[4] = {0, 0, -W / 2, W / 2};
4541 int yo[4] = {H / 2, -H / 2, 0, 0};
4542
4543 sprite = crop_sprite(sprite, x[dir], y[dir], W / 2, H / 2,
4544 t->sprites.mask.tile, xo[dir], yo[dir], 1.0f,
4545 FALSE);
4546 /* We allocated new sprite with crop_sprite. Store its
4547 * address so we can free it. */
4548 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
4549 dlp->allocated.p[vec_size] = sprite;
4550 } else {
4551 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer);
4552 }
4553
4554 dlp->cells[i] = sprite;
4555 }
4556 break;
4557 };
4558 }
4559 }
4560 break;
4561 };
4562 }
4563
4564 /* Try an optional special name */
4565 fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
4566 draw->blender
4568 nullptr, "blend terrain",
4569 terrain_rule_name(pterrain), TRUE);
4570
4571 if (draw->blending > 0) {
4572 const int bl = draw->blending - 1;
4573
4574 if (draw->blender == nullptr) {
4575 int li = 0;
4576
4577 /* Try an already loaded base */
4578 while (draw->blender == nullptr
4579 && li < draw->blending
4580 && 0 < draw->layer[li].base.size) {
4581 draw->blender = draw->layer[li++].base.p[0];
4582 }
4583 }
4584
4585 if (draw->blender == nullptr) {
4586 /* Try an unloaded base name */
4587 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", bl, draw->name);
4588 draw->blender
4589 = tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
4590 nullptr, "base (blend) terrain",
4591 terrain_rule_name(pterrain), TRUE);
4592 }
4593 }
4594
4595 if (draw->blender != nullptr) {
4596 /* Set up blending sprites. This only works in iso-view! */
4597 const int W = t->normal_tile_width;
4598 const int H = t->normal_tile_height;
4599 const int offsets[4][2] = {
4600 {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4601 };
4602 enum direction4 dir = 0;
4603
4604 for (; dir < 4; dir++) {
4605 draw->blend[dir] = crop_sprite(draw->blender, offsets[dir][0],
4606 offsets[dir][1], W / 2, H / 2,
4607 t->sprites.dither_tile, 0, 0, 1.0f,
4608 FALSE);
4609 }
4610 }
4611
4612 draw->init = TRUE;
4613 t->sprites.drawing[terrain_index(pterrain)] = draw;
4614}
4615
4616/************************************************************************/
4621 struct government *gov)
4622{
4625 gov->graphic_alt, nullptr, "government",
4627
4628 /* Should probably do something if nullptr, eg generic default? */
4629}
4630
4631/************************************************************************/
4636 struct nation_type *nation)
4637{
4638 char *tags[] = {nation->flag_graphic_str,
4639 nation->flag_graphic_alt,
4640 "unknown", nullptr};
4641 int i;
4642 struct sprite *flag = nullptr, *shield = nullptr;
4643 char buf[1024];
4645
4646 for (i = 0; tags[i] && !flag; i++) {
4647 fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
4648 flag = load_sprite(t, buf, TRUE, TRUE, svgflag);
4649 }
4650 for (i = 0; tags[i] && !shield; i++) {
4651 fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
4652 shield = load_sprite(t, buf, TRUE, TRUE, svgflag);
4653 }
4654 if (!flag || !shield) {
4655 /* Should never get here because of the f.unknown fallback. */
4657 _("Nation %s: no national flag."), nation_rule_name(nation));
4658 }
4659
4661 t->sprites.nation_flag.p[nation_index(nation)] = flag;
4662
4664 t->sprites.nation_shield.p[nation_index(nation)] = shield;
4665}
4666
4667/************************************************************************/
4670struct sprite *get_city_flag_sprite(const struct tileset *t,
4671 const struct city *pcity)
4672{
4674}
4675
4676/************************************************************************/
4679static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
4680 const struct unit *punit)
4681{
4682 struct nation_type *pnation = nation_of_unit(punit);
4683
4685 return t->sprites.nation_shield.p[nation_index(pnation)];
4686 } else {
4687 return t->sprites.nation_flag.p[nation_index(pnation)];
4688 }
4689}
4690
4691#define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
4692#define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
4693
4694#define ADD_SPRITE_SIZE(s, draw_fog, x_offset, y_offset, w_in, h_in) \
4695 (fc_assert(s != nullptr), \
4696 sprs->sprite = s, \
4697 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
4698 sprs->offset_x = x_offset, \
4699 sprs->offset_y = y_offset, \
4700 sprs->w = w_in, \
4701 sprs->h = h_in, \
4702 sprs++)
4703#define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
4704 ADD_SPRITE_SIZE(s, draw_fog, x_offset, y_offset, 0, 0)
4705#define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
4706#define ADD_SPRITE_FULL(s) \
4707 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4708
4709#define ADD_ANIM_SPRITE(s, draw_fog, x_offset, y_offset) \
4710 ADD_SPRITE(anim_get_current_frame(s), draw_fog, x_offset, y_offset)
4711#define ADD_ANIM_SPRITE_SIMPLE(s) \
4712 ADD_SPRITE(anim_get_current_frame(s), TRUE, 0, 0)
4713#define ADD_ANIM_FULL(s) \
4714 ADD_SPRITE(anim_get_current_frame(s), TRUE, \
4715 FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4716
4717#define ADD_FRAME0_SIMPLE(s) ADD_SPRITE_SIMPLE(s->sprites[0])
4718#define ADD_FRAME0_FULL(s) \
4719 ADD_SPRITE_FULL(s->sprites[0])
4720
4721/************************************************************************/
4728static void build_tile_data(const struct tile *ptile,
4729 struct terrain *pterrain,
4730 struct terrain **tterrain_near,
4732{
4733 enum direction8 dir;
4734
4735 /* Loop over all adjacent tiles. We should have an iterator for this. */
4736 for (dir = 0; dir < 8; dir++) {
4737 struct tile *tile1 = mapstep(&(wld.map), ptile, dir);
4738
4741
4742 if (terrain1 != nullptr) {
4743 tterrain_near[dir] = terrain1;
4745 continue;
4746 }
4747 log_error("build_tile_data() tile (%d,%d) has no terrain!",
4748 TILE_XY(tile1));
4749 }
4750 /* At the edges of the (known) map, pretend the same terrain continued
4751 * past the edge of the map. */
4752 tterrain_near[dir] = pterrain;
4754 }
4755}
4756
4757/************************************************************************/
4760static int fill_unit_type_sprite_array(const struct tileset *t,
4761 struct drawn_sprite *sprs,
4762 const struct unit_type *putype,
4763 enum unit_activity activity,
4764 enum direction8 facing)
4765{
4766 struct drawn_sprite *save_sprs = sprs;
4767 struct sprite *uspr = get_unittype_sprite(t, putype, activity, facing);
4768
4772
4773 return sprs - save_sprs;
4774}
4775
4776/************************************************************************/
4779static int fill_unit_sprite_array(const struct tileset *t,
4780 struct drawn_sprite *sprs,
4781 const struct unit *punit,
4782 int stack, bool backdrop)
4783{
4784 struct drawn_sprite *save_sprs = sprs;
4785 int ihp;
4786 const struct unit_type *ptype = unit_type_get(punit);
4787
4788 if (backdrop) {
4794 }
4795 } else {
4796 /* Taken care of in the LAYER_BACKGROUND. */
4797 }
4798 }
4799
4800 /* Add the sprite for the unit type. */
4803
4804 if (t->sprites.unit.loaded && unit_transported(punit)) {
4805 ADD_SPRITE_FULL(t->sprites.unit.loaded);
4806 }
4807
4808 if (punit->activity != ACTIVITY_IDLE) {
4809 struct sprite *s = nullptr;
4810
4811 switch (punit->activity) {
4812 case ACTIVITY_MINE:
4813 if (punit->activity_target == nullptr) {
4814 s = t->sprites.unit.plant;
4815 } else {
4817 }
4818 break;
4819 case ACTIVITY_PLANT:
4820 s = t->sprites.unit.plant;
4821 break;
4822 case ACTIVITY_IRRIGATE:
4823 if (punit->activity_target == nullptr) {
4824 s = t->sprites.unit.cultivate;
4825 } else {
4827 }
4828 break;
4829 case ACTIVITY_CULTIVATE:
4830 s = t->sprites.unit.cultivate;
4831 break;
4832 case ACTIVITY_CLEAN:
4834 break;
4835 case ACTIVITY_PILLAGE:
4837 if (s == nullptr) {
4838 s = t->sprites.unit.pillage;
4839 }
4840 break;
4841 case ACTIVITY_EXPLORE:
4842 /* Drawn below as the server side agent. */
4843 break;
4844 case ACTIVITY_FORTIFIED:
4845 s = t->sprites.unit.fortified;
4846 break;
4848 s = t->sprites.unit.fortifying;
4849 break;
4850 case ACTIVITY_SENTRY:
4851 s = t->sprites.unit.sentry;
4852 break;
4853 case ACTIVITY_GOTO:
4854 s = t->sprites.unit.go_to;
4855 break;
4856 case ACTIVITY_TRANSFORM:
4857 s = t->sprites.unit.transform;
4858 break;
4859 case ACTIVITY_BASE:
4860 case ACTIVITY_GEN_ROAD:
4862 break;
4863 case ACTIVITY_CONVERT:
4864 s = t->sprites.unit.convert;
4865 break;
4866 default:
4867 break;
4868 }
4869
4870 if (s != nullptr) {
4873 }
4874 }
4875
4876 {
4877 struct sprite *s = nullptr;
4878 int offset_x = 0;
4879 int offset_y = 0;
4880
4881 switch (punit->ssa_controller) {
4882 case SSA_NONE:
4883 break;
4884 case SSA_AUTOWORKER:
4885 s = t->sprites.unit.auto_worker;
4886 break;
4887 case SSA_AUTOEXPLORE:
4888 s = t->sprites.unit.auto_explore;
4889 /* Specified as an activity in the tileset. */
4892 break;
4893 default:
4894 s = t->sprites.unit.auto_attack;
4895 break;
4896 }
4897
4898 if (s != nullptr) {
4899 ADD_SPRITE(s, TRUE,
4902 }
4903 }
4904
4905 if (unit_has_orders(punit)) {
4906 if (punit->orders.repeat) {
4907 ADD_SPRITE_FULL(t->sprites.unit.patrol);
4908 } else if (punit->activity != ACTIVITY_IDLE) {
4909 ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
4910 } else {
4911 ADD_SPRITE(t->sprites.unit.go_to, TRUE,
4914 }
4915 }
4916
4917 if (t->sprites.unit.action_decision_want != nullptr
4919 ADD_ANIM_SPRITE(t->sprites.unit.action_decision_want, TRUE,
4922 }
4923
4925 ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
4926 }
4927
4928 if (t->sprites.unit.lowfuel
4929 && utype_fuel(ptype)
4930 && punit->fuel == 1
4931 && punit->moves_left <= 2 * SINGLE_MOVE) {
4932 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4933 ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
4934 }
4935 if (t->sprites.unit.tired
4937 && ptype->move_rate > 0) {
4938 /* Show a "tired" graphic if the unit has fewer than one move
4939 * remaining, except for units for which it's full movement. */
4940 ADD_SPRITE_FULL(t->sprites.unit.tired);
4941 }
4942
4943 if (stack == 1 && punit->client.occupied) {
4944 ADD_SPRITE_FULL(t->sprites.unit.stack[0]);
4945 } else if (stack > 1) {
4947 && t->sprites.unit.num_stack_sprites >= stack) {
4948 ADD_SPRITE(t->sprites.unit.stack[stack - 1], FALSE,
4950 } else {
4951 ADD_SPRITE_FULL(t->sprites.unit.stack[0]);
4952 }
4953 }
4954
4955 if (t->sprites.unit.vet_lev[punit->veteran]) {
4957 }
4958
4959 ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
4960 ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
4961 ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
4962
4963 return sprs - save_sprs;
4964}
4965
4966/************************************************************************/
4969static int fill_road_corner_sprites(const struct tileset *t,
4970 const struct extra_type *pextra,
4971 struct drawn_sprite *sprs,
4972 bool road, bool *road_near,
4973 bool hider, bool *hider_near)
4974{
4975 struct drawn_sprite *saved_sprs = sprs;
4976 int i;
4977 int extra_idx = extra_index(pextra);
4978
4979 if (is_cardinal_only_road(pextra)) {
4980 return 0;
4981 }
4982
4983 /* Roads going diagonally adjacent to this tile need to be
4984 * partly drawn on this tile. */
4985
4986 /* Draw the corner sprite if:
4987 * - There is a diagonal road (not rail!) between two adjacent tiles.
4988 * - There is no diagonal road (not rail!) that intersects this road.
4989 * The logic is simple: roads are drawn underneath railrods, but are
4990 * not always covered by them (even in the corners!). But if a railroad
4991 * connects two tiles, only the railroad (no road) is drawn between
4992 * those tiles.
4993 */
4994 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4995 enum direction8 dir = t->valid_tileset_dirs[i];
4996
4997 if (!is_cardinal_tileset_dir(t, dir)) {
4998 /* Draw corner sprites for this non-cardinal direction. */
4999 int cw = (i + 1) % t->num_valid_tileset_dirs;
5000 int ccw
5002 enum direction8 cwdir = t->valid_tileset_dirs[cw];
5004
5005 if (t->sprites.extras[extra_idx].u.road.corner[dir]
5007 && !(hider_near[cwdir] && hider_near[ccwdir]))
5008 && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
5010 }
5011 }
5012 }
5013
5014 return sprs - saved_sprs;
5015}
5016
5017/************************************************************************/
5020static int fill_road_sprite_array(const struct tileset *t,
5021 const struct extra_type *pextra,
5022 struct drawn_sprite *sprs,
5025 struct terrain *tterrain_near[8],
5026 const struct city *pcity)
5027{
5028 struct drawn_sprite *saved_sprs = sprs;
5029 bool road, road_near[8], hider, hider_near[8];
5030 bool land_near[8], hland_near[8];
5031 bool draw_road[8], draw_single_road;
5032 enum direction8 dir;
5033 int extra_idx = -1;
5034 bool cl = FALSE;
5035 enum extrastyle_id extrastyle;
5036 const struct road_type *proad = extra_road_get(pextra);
5037
5038 extra_idx = extra_index(pextra);
5039
5040 extrastyle = t->sprites.extras[extra_idx].extrastyle;
5041
5042 if (extra_has_flag(pextra, EF_CONNECT_LAND)) {
5043 cl = TRUE;
5044 } else {
5045 int i;
5046
5047 for (i = 0; i < 8; i++) {
5048 land_near[i] = FALSE;
5049 }
5050 }
5051
5052 /* Fill some data arrays. rail_near and road_near store whether road/rail
5053 * is present in the given direction. draw_rail and draw_road store
5054 * whether road/rail is to be drawn in that direction. draw_single_road
5055 * and draw_single_rail store whether we need an isolated road/rail to be
5056 * drawn. */
5058
5059 hider = FALSE;
5062 hider = TRUE;
5063 break;
5064 }
5066
5067 if (road && (!pcity || !gui_options.draw_cities) && !hider) {
5069 } else {
5071 }
5072
5073 for (dir = 0; dir < 8; dir++) {
5074 bool roads_exist;
5075
5076 /* Check if there is adjacent road/rail. */
5077 if (!is_cardinal_only_road(pextra)
5078 || is_cardinal_tileset_dir(t, dir)) {
5079 road_near[dir] = FALSE;
5080 extra_type_list_iterate(proad->integrators, iextra) {
5082 road_near[dir] = TRUE;
5083 break;
5084 }
5086 if (cl) {
5087 land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
5089 }
5090 } else {
5091 road_near[dir] = FALSE;
5092 land_near[dir] = FALSE;
5093 }
5094
5095 /* Draw rail/road if there is a connection from this tile to the
5096 * adjacent tile. But don't draw road if there is also a rail
5097 * connection. */
5098 roads_exist = road && (road_near[dir] || land_near[dir]);
5099 draw_road[dir] = roads_exist;
5100 hider_near[dir] = FALSE;
5101 hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
5104 bool hider_dir = FALSE;
5105 bool land_dir = FALSE;
5106
5108 || is_cardinal_tileset_dir(t, dir)) {
5110 hider_near[dir] = TRUE;
5111 hider_dir = TRUE;
5112 }
5113 if (hland_near[dir]
5116 land_dir = TRUE;
5117 }
5118 if (hider_dir || land_dir) {
5120 draw_road[dir] = FALSE;
5121 }
5122 }
5123 }
5125
5126 /* Don't draw an isolated road/rail if there's any connection.
5127 * draw_single_road would be true in the first place only if start tile has road,
5128 * so it will have road connection with any adjacent road tile. We check from real
5129 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
5130 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
5131 * draw single road in that case either. */
5132 if (draw_single_road && road_near[dir]) {
5134 }
5135 }
5136
5137 /* Draw road corners */
5138 sprs
5140
5141 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
5142 /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
5143 * This means we only need a few sprites, but a lot of drawing is
5144 * necessary and it generally doesn't look very good. */
5145 int i;
5146
5147 /* First draw roads under rails. */
5148 if (road) {
5149 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
5150 if (draw_road[t->valid_tileset_dirs[i]]) {
5152 }
5153 }
5154 }
5155 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
5156 /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
5157 * road connections, one sprite for diagonal road connections.
5158 * This means we need about 4x more sprites than in style 0, but up to
5159 * 4x less drawing is needed. The drawing quality may also be
5160 * improved. */
5161
5162 /* First draw roads under rails. */
5163 if (road) {
5164 int road_even_tileno = 0, road_odd_tileno = 0, i;
5165
5166 for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
5167 enum direction8 even = t->valid_tileset_dirs[2 * i];
5168 enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
5169
5170 if (draw_road[even]) {
5171 road_even_tileno |= 1 << i;
5172 }
5173 if (draw_road[odd]) {
5174 road_odd_tileno |= 1 << i;
5175 }
5176 }
5177
5178 /* Draw the cardinal/even roads first. */
5179 if (road_even_tileno != 0) {
5181 }
5182 if (road_odd_tileno != 0) {
5184 }
5185 }
5186 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
5187 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
5188 * entire finished tiles, with a bitwise index of the presence of
5189 * roads in each direction. */
5190
5191 /* Draw roads first */
5192 if (road) {
5193 int road_tileno = 0, i;
5194
5195 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
5197
5198 if (draw_road[vdir]) {
5199 road_tileno |= 1 << i;
5200 }
5201 }
5202
5203 if (road_tileno != 0 || draw_single_road) {
5205 }
5206 }
5207 } else {
5209 }
5210
5211 /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
5212 ESTYLE_ROAD_PARITY_COMBINED only). */
5213 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
5214 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
5215 if (draw_single_road) {
5217 }
5218 }
5219
5220 return sprs - saved_sprs;
5221}
5222
5223/************************************************************************/
5232static int get_irrigation_index(const struct tileset *t,
5233 struct extra_type *pextra,
5235{
5236 int tileno = 0, i;
5237
5238 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5239 enum direction8 dir = t->cardinal_tileset_dirs[i];
5240
5241 if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
5242 tileno |= 1 << i;
5243 }
5244 }
5245
5246 return tileno;
5247}
5248
5249/************************************************************************/
5252static int fill_irrigation_sprite_array(const struct tileset *t,
5253 struct drawn_sprite *sprs,
5256 const struct city *pcity)
5257{
5258 struct drawn_sprite *saved_sprs = sprs;
5259
5260 /* We don't draw the irrigation if there's a city (it just gets overdrawn
5261 * anyway, and ends up looking bad). */
5262 if (!(pcity && gui_options.draw_cities)) {
5264 if (is_extra_drawing_enabled(pextra)) {
5265 int eidx = extra_index(pextra);
5266
5267 if (BV_ISSET(textras, eidx)) {
5268 bool hidden = FALSE;
5269
5270 extra_type_list_iterate(pextra->hiders, phider) {
5272 hidden = TRUE;
5273 break;
5274 }
5276
5277 if (!hidden) {
5278 int idx = get_irrigation_index(t, pextra, textras_near);
5279
5281 }
5282 }
5283 }
5285 }
5286
5287 return sprs - saved_sprs;
5288}
5289
5290/************************************************************************/
5294static int fill_city_overlays_sprite_array(const struct tileset *t,
5295 struct drawn_sprite *sprs,
5296 const struct tile *ptile,
5297 const struct city *citymode)
5298{
5299 const struct city *pcity;
5300 const struct city *pwork;
5301 struct unit *psettler;
5302 struct drawn_sprite *saved_sprs = sprs;
5303 int city_x, city_y;
5304 const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
5305
5306 if (ptile == nullptr || TILE_UNKNOWN == client_tile_get_known(ptile)) {
5307 return 0;
5308 }
5309 pwork = tile_worked(ptile);
5310
5311 if (citymode) {
5312 pcity = citymode;
5313 } else {
5315 }
5316
5317 /* Below code does not work if pcity is invisible.
5318 * Make sure it is not. */
5319 fc_assert_ret_val(pcity == nullptr || pcity->tile != nullptr, 0);
5320
5321 if (pcity && !pcity->tile) {
5322 pcity = nullptr;
5323 }
5324
5325 if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
5326 /* FIXME: check elsewhere for valid tile (instead of above) */
5327
5328 if (!citymode && pcity->client.colored) {
5329 /* Add citymap overlay for a city. */
5331
5332 if (pwork != nullptr && pwork == pcity) {
5334 } else if (city_can_work_tile(pcity, ptile)) {
5336 }
5337 } else if (pwork != nullptr && pwork == pcity
5339
5340 /* Add on the tile output sprites.
5341 * NOTE: To show correct output on end of turn
5342 * base_city_celebrating() must be used instead of city_celebrating()
5343 * mirroring the behavior of the server that does so in
5344 * city_tile_cache_update(). */
5346 int food = city_tile_output(pcity, ptile, celebrating, O_FOOD);
5347 int shields = city_tile_output(pcity, ptile, celebrating, O_SHIELD);
5348 int trade = city_tile_output(pcity, ptile, celebrating, O_TRADE);
5349
5350 const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
5351 const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
5352
5353 food = CLIP(0, food / game.info.granularity, NUM_TILES_DIGITS - 1);
5354 shields = CLIP(0, shields / game.info.granularity, NUM_TILES_DIGITS - 1);
5355 trade = CLIP(0, trade / game.info.granularity, NUM_TILES_DIGITS - 1);
5356
5358 ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
5360 }
5361 } else if (psettler && psettler->client.colored) {
5362 /* Add citymap overlay for a unit. */
5363 int idx = psettler->client.color_index % NUM_CITY_COLORS;
5364
5366 }
5367
5368 return sprs - saved_sprs;
5369}
5370
5371/************************************************************************/
5375static int fill_terrain_sprite_blending(const struct tileset *t,
5376 struct drawn_sprite *sprs,
5377 const struct tile *ptile,
5378 const struct terrain *pterrain,
5379 struct terrain **tterrain_near)
5380{
5381 struct drawn_sprite *saved_sprs = sprs;
5382 const int W = t->normal_tile_width, H = t->normal_tile_height;
5383 const int offsets[4][2] = {
5384 {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
5385 };
5386 enum direction4 dir = 0;
5387
5388 /*
5389 * We want to mark unknown tiles so that an unreal tile will be
5390 * given the same marking as our current tile - that way we won't
5391 * get the "unknown" dither along the edge of the map.
5392 */
5393 for (; dir < 4; dir++) {
5394 struct tile *tile1 = mapstep(&(wld.map), ptile, DIR4_TO_DIR8[dir]);
5395 struct terrain *other;
5396
5397 if (!tile1
5399 || pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
5400 || (0 == t->sprites.drawing[terrain_index(other)]->blending
5401 && t->sprites.drawing[terrain_index(other)]->blender == nullptr)) {
5402 continue;
5403 }
5404
5406 offsets[dir][0], offsets[dir][1]);
5407 }
5408
5409 return sprs - saved_sprs;
5410}
5411
5412/************************************************************************/
5415static int fill_fog_sprite_array(const struct tileset *t,
5416 struct drawn_sprite *sprs,
5417 const struct tile *ptile,
5418 const struct tile_edge *pedge,
5419 const struct tile_corner *pcorner)
5420{
5421 struct drawn_sprite *saved_sprs = sprs;
5422
5424 && ptile != nullptr
5426 /* With FOG_AUTO, fog is done this way. */
5428 }
5429
5432 int i, tileno = 0;
5433
5434 for (i = 3; i >= 0; i--) {
5435 const int unknown = 0, fogged = 1, known = 2;
5436 int value = -1;
5437
5438 if (!pcorner->tile[i]) {
5439 value = fogged;
5440 } else {
5441 switch (client_tile_get_known(pcorner->tile[i])) {
5442 case TILE_KNOWN_SEEN:
5443 value = known;
5444 break;
5445 case TILE_KNOWN_UNSEEN:
5446 value = fogged;
5447 break;
5448 case TILE_UNKNOWN:
5449 value = unknown;
5450 break;
5451 }
5452 }
5453 fc_assert(value >= 0 && value < 3);
5454
5455 tileno = tileno * 3 + value;
5456 }
5457
5458 if (t->sprites.tx.fullfog[tileno]) {
5460 }
5461 }
5462
5463 return sprs - saved_sprs;
5464}
5465
5466/************************************************************************/
5470 struct drawn_sprite *sprs,
5471 int l, /* layer_num */
5472 const struct tile *ptile,
5473 const struct terrain *pterrain,
5474 struct terrain **tterrain_near,
5475 struct drawing_data *draw)
5476{
5477 struct drawn_sprite *saved_sprs = sprs;
5478 struct drawing_layer *dlp = &draw->layer[l];
5479 int this = dlp->match_index[0];
5480 int that = dlp->match_index[1];
5481 int ox = dlp->offset_x;
5482 int oy = dlp->offset_y;
5483 int i;
5484
5485#define MATCH(dir) \
5486 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
5487 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
5488 : -1)
5489
5490 switch (dlp->sprite_type) {
5491 case CELL_WHOLE:
5492 {
5493 switch (dlp->match_style) {
5494 case MATCH_NONE:
5495 {
5496 int count = sprite_vector_size(&dlp->base);
5497
5498 if (count > 0) {
5499 /* Pseudo-random reproducible algorithm to pick a sprite. Use modulo
5500 * to limit the number to a handleable size [0..32000). */
5501 count = fc_randomly(tile_index(ptile) % 32000, count);
5502
5503 if (dlp->is_tall) {
5506 }
5507 ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
5508 }
5509 break;
5510 }
5511 case MATCH_SAME:
5512 {
5513 int tileno = 0;
5514
5515 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5516 enum direction8 dir = t->cardinal_tileset_dirs[i];
5517
5518 if (MATCH(dir) == this) {
5519 tileno |= 1 << i;
5520 }
5521 }
5522
5523 if (dlp->is_tall) {
5526 }
5527 ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
5528 break;
5529 }
5530 case MATCH_PAIR:
5531 case MATCH_FULL:
5532 fc_assert(FALSE); /* Not yet defined */
5533 break;
5534 };
5535 break;
5536 }
5537 case CELL_CORNER:
5538 {
5539 /* Divide the tile up into four rectangular cells. Each of these
5540 * cells covers one corner, and each is adjacent to 3 different
5541 * tiles. For each cell we pick a sprite based upon the adjacent
5542 * terrains at each of those tiles. Thus, we have 8 different sprites
5543 * for each of the 4 cells (32 sprites total).
5544 *
5545 * These arrays correspond to the direction4 ordering. */
5546 const int W = t->normal_tile_width;
5547 const int H = t->normal_tile_height;
5548 const int iso_offsets[4][2] = {
5549 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
5550 };
5551 const int noniso_offsets[4][2] = {
5552 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
5553 };
5554
5555 /* Put corner cells */
5556 for (i = 0; i < NUM_CORNER_DIRS; i++) {
5557 const int count = dlp->match_indices;
5558 int array_index = 0;
5559 enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
5560 int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
5561 int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
5562 int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
5563 struct sprite *s;
5564
5565 /* Synthesize 4 dimensional array? */
5566 switch (dlp->match_style) {
5567 case MATCH_NONE:
5568 /* We have no need for matching, just plug the piece in place. */
5569 break;
5570 case MATCH_SAME:
5571 array_index = array_index * 2 + (m[2] != this);
5572 array_index = array_index * 2 + (m[1] != this);
5573 array_index = array_index * 2 + (m[0] != this);
5574 break;
5575 case MATCH_PAIR:
5576 array_index = array_index * 2 + (m[2] == that);
5577 array_index = array_index * 2 + (m[1] == that);
5578 array_index = array_index * 2 + (m[0] == that);
5579 break;
5580 case MATCH_FULL:
5581 default:
5582 if (count > 0) {
5583 int n[3];
5584 int j;
5585
5586 for (j = 0; j < 3; j++) {
5587 int k;
5588
5589 for (k = 0; k < count; k++) {
5590 n[j] = k; /* Default to last entry */
5591 if (m[j] == dlp->match_index[k]) {
5592 break;
5593 }
5594 }
5595 }
5596 array_index = array_index * count + n[2];
5597 array_index = array_index * count + n[1];
5598 array_index = array_index * count + n[0];
5599 }
5600 break;
5601 };
5602
5604
5605 s = dlp->cells[array_index];
5606 if (s) {
5607 ADD_SPRITE(s, TRUE, x, y);
5608 }
5609 }
5610 break;
5611 }
5612 };
5613#undef MATCH
5614
5615 return sprs - saved_sprs;
5616}
5617
5618/************************************************************************/
5623 struct drawn_sprite *sprs,
5624 const struct tile *ptile,
5625 struct terrain **tterrain_near)
5626{
5627 struct drawn_sprite *saved_sprs = sprs;
5628 int i, tileno;
5629 struct tile *adjc_tile;
5630
5631#define UNKNOWN(dir) \
5632 ((adjc_tile = mapstep(&(wld.map), ptile, (dir))) \
5633 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
5634
5635 switch (t->darkness_style) {
5636 case DARKNESS_NONE:
5637 break;
5638 case DARKNESS_ISORECT:
5639 for (i = 0; i < 4; i++) {
5640 const int W = t->normal_tile_width, H = t->normal_tile_height;
5641 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
5642
5643 if (UNKNOWN(DIR4_TO_DIR8[i])) {
5645 offsets[i][0], offsets[i][1]);
5646 }
5647 }
5648 break;
5650 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5651 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5653 }
5654 }
5655 break;
5656 case DARKNESS_CARD_FULL:
5657 /* We're looking to find the INDEX_NSEW for the directions that
5658 * are unknown. We want to mark unknown tiles so that an unreal
5659 * tile will be given the same marking as our current tile - that
5660 * way we won't get the "unknown" dither along the edge of the
5661 * map. */
5662 tileno = 0;
5663 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5664 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5665 tileno |= 1 << i;
5666 }
5667 }
5668
5669 if (tileno != 0) {
5671 }
5672 break;
5673 case DARKNESS_CORNER:
5674 /* Handled separately. */
5675 break;
5676 };
5677#undef UNKNOWN
5678
5679 return sprs - saved_sprs;
5680}
5681
5682/************************************************************************/
5687 struct drawn_sprite *sprs,
5688 int layer_num,
5689 const struct tile *ptile,
5690 const struct terrain *pterrain,
5691 struct terrain **tterrain_near)
5692{
5693 struct sprite *sprite;
5694 struct drawn_sprite *saved_sprs = sprs;
5695 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
5696 const int l = (draw->is_reversed
5697 ? (draw->num_layers - layer_num - 1) : layer_num);
5698
5700
5701 /* Skip the normal drawing process. */
5702 /* FIXME: this should avoid calling load_sprite since it's slow and
5703 * increases the refcount without limit. */
5704 if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite,
5705 TRUE, FALSE, FALSE))) {
5706 if (l == 0) {
5708 return 1;
5709 } else {
5710 return 0;
5711 }
5712 }
5713
5715 sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
5716
5717 if ((l + 1) == draw->blending) {
5718 sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
5719 }
5720 }
5721
5722 return sprs - saved_sprs;
5723}
5724
5725/************************************************************************/
5732{
5733 /* Display an outline for city-builder type units if they are selected,
5734 * and on a tile where a city can be built.
5735 * But suppress the outline if the unit has orders (likely it is in
5736 * transit to somewhere else and this will just slow down redraws). */
5743}
5744
5745/************************************************************************/
5748static int fill_grid_sprite_array(const struct tileset *t,
5749 struct drawn_sprite *sprs,
5750 const struct tile *ptile,
5751 const struct tile_edge *pedge,
5752 const struct tile_corner *pcorner,
5753 const struct unit *punit,
5754 const struct city *pcity,
5755 const struct city *citymode)
5756{
5757 struct drawn_sprite *saved_sprs = sprs;
5758
5759 if (pedge) {
5760 bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
5761 bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
5762 int i;
5763 struct unit_list *pfocus_units = get_units_in_focus();
5764
5765 for (i = 0; i < NUM_EDGE_TILES; i++) {
5766 int dummy_x, dummy_y;
5767 const struct tile *tile = pedge->tile[i];
5768 struct player *powner = tile ? tile_owner(tile) : nullptr;
5769
5771 unit[i] = FALSE;
5772 if (tile && !citymode) {
5775 struct tile *utile = unit_tile(pfocus_unit);
5776 int radius = game.info.init_city_radius_sq
5778 nullptr,
5779 &(const struct req_context) {
5780 .player = unit_owner(pfocus_unit),
5781 .tile = utile,
5782 },
5783 nullptr,
5785 );
5786
5787 if (city_tile_to_city_map(&dummy_x, &dummy_y, radius,
5788 utile, tile)) {
5789 unit[i] = TRUE;
5790 break;
5791 }
5792 }
5794 }
5795 worked[i] = FALSE;
5796
5797 city[i] = (tile
5798 && (powner == nullptr || client.conn.playing == nullptr
5799 || powner == client.conn.playing)
5801 if (city[i]) {
5802 if (citymode) {
5803 /* In citymode, we only draw worked tiles for this city - other
5804 * tiles may be marked as unavailable. */
5805 worked[i] = (tile_worked(tile) == citymode);
5806 } else {
5807 worked[i] = (tile_worked(tile) != nullptr);
5808 }
5809 }
5810 }
5811
5812 if (mapdeco_is_highlight_set(pedge->tile[0])
5813 || mapdeco_is_highlight_set(pedge->tile[1])) {
5816 && pedge->tile[0] && pedge->tile[1]
5817 && known[0] && known[1]
5818 && (is_ocean_tile(pedge->tile[0])
5819 ^ is_ocean_tile(pedge->tile[1]))) {
5821 } else {
5823 if (worked[0] || worked[1]) {
5825 } else if (city[0] || city[1]) {
5827 } else if (known[0] || known[1]) {
5829 }
5830 }
5832 if (XOR(city[0], city[1])) {
5834 }
5835 if (XOR(unit[0], unit[1])) {
5837 }
5838 }
5839 }
5840
5843 && known[0]
5844 && known[1]) {
5845 struct player *owner0 = tile_owner(pedge->tile[0]);
5846 struct player *owner1 = tile_owner(pedge->tile[1]);
5847
5848 if (owner0 != owner1) {
5849 if (owner0) {
5850 int plrid = player_index(owner0);
5852 [pedge->type][0]);
5853 }
5854 if (owner1) {
5855 int plrid = player_index(owner1);
5857 [pedge->type][1]);
5858 }
5859 }
5860 }
5861 } else if (ptile != nullptr && TILE_UNKNOWN != client_tile_get_known(ptile)) {
5862 int cx, cy;
5863
5864 if (citymode
5865 /* Test to ensure valid coordinates? */
5866 && city_base_to_city_map(&cx, &cy, citymode, ptile)
5867 && !client_city_can_work_tile(citymode, ptile)) {
5869 }
5870
5871 if (gui_options.draw_native && citymode == nullptr) {
5872 bool native = TRUE;
5873 struct unit_list *pfocus_units = get_units_in_focus();
5874
5876 if (!is_native_tile(unit_type_get(pfocus), ptile)) {
5877 native = FALSE;
5878 break;
5879 }
5881
5882 if (!native) {
5883 if (t->sprites.grid.nonnative != nullptr) {
5885 } else {
5887 }
5888 }
5889 }
5890 }
5891
5892 return sprs - saved_sprs;
5893}
5894
5895/************************************************************************/
5898static int fill_goto_sprite_array(const struct tileset *t,
5899 struct drawn_sprite *sprs,
5900 const struct tile *ptile,
5901 const struct tile_edge *pedge,
5902 const struct tile_corner *pcorner)
5903{
5904 struct drawn_sprite *saved_sprs = sprs;
5905 struct sprite *sprite;
5906 bool warn = FALSE;
5907 enum goto_tile_state state;
5908 int length;
5909 bool waypoint;
5910
5911 if (goto_tile_state(ptile, &state, &length, &waypoint)) {
5912 if (length >= 0) {
5913 fc_assert(state >= 0);
5914 fc_assert(state < ARRAY_SIZE(t->sprites.path.s));
5915
5916 sprite = t->sprites.path.s[state].specific;
5917 if (sprite != nullptr) {
5918 ADD_SPRITE(sprite, FALSE, 0, 0);
5919 }
5920
5921 sprite = t->sprites.path.s[state].turns[length % 10];
5923 if (length >= 10) {
5924 sprite = t->sprites.path.s[state].turns_tens[(length / 10) % 10];
5926 if (length >= 100) {
5927 sprite = t->sprites.path.s[state].turns_hundreds[(length / 100)
5928 % 10];
5929
5930 if (sprite != nullptr) {
5932 if (length >= 1000) {
5933 warn = TRUE;
5934 }
5935 } else {
5936 warn = TRUE;
5937 }
5938 }
5939 }
5940 }
5941
5942 if (waypoint) {
5944 }
5945
5946 if (warn) {
5947 /* Warn only once by tileset. */
5948 static char last_reported[256] = "";
5949
5950 if (0 != strcmp(last_reported, t->name)) {
5951 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5952 "such as %d. Path not displayed as expected."),
5953 t->name, length);
5955 }
5956 }
5957 }
5958
5959 return sprs - saved_sprs;
5960}
5961
5962/************************************************************************/
5966static bool is_extra_drawing_enabled(struct extra_type *pextra)
5967{
5968 bool no_disable = TRUE; /* Draw if matches no cause */
5969
5970 if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
5972 return TRUE;
5973 }
5974 no_disable = FALSE;
5975 }
5976 if (is_extra_caused_by(pextra, EC_POLLUTION)
5977 || is_extra_caused_by(pextra, EC_FALLOUT)) {
5979 return TRUE;
5980 }
5981 no_disable = FALSE;
5982 }
5983 if (is_extra_caused_by(pextra, EC_MINE)) {
5984 if (gui_options.draw_mines) {
5985 return TRUE;
5986 }
5987 no_disable = FALSE;
5988 }
5989 if (is_extra_caused_by(pextra, EC_RESOURCE)) {
5991 return TRUE;
5992 }
5993 no_disable = FALSE;
5994 }
5995 if (is_extra_removed_by(pextra, ERM_ENTER)) {
5996 if (gui_options.draw_huts) {
5997 return TRUE;
5998 }
5999 no_disable = FALSE;
6000 }
6001 if (is_extra_caused_by(pextra, EC_BASE)) {
6003 return TRUE;
6004 }
6005 no_disable = FALSE;
6006 }
6007 if (is_extra_caused_by(pextra, EC_ROAD)) {
6008 if (gui_options.draw_paths) {
6009 return TRUE;
6010 }
6011 no_disable = FALSE;
6012 }
6013
6014 return no_disable;
6015}
6016
6017/************************************************************************/
6034 struct drawn_sprite *sprs, enum mapview_layer layer,
6035 const struct tile *ptile,
6036 const struct tile_edge *pedge,
6037 const struct tile_corner *pcorner,
6038 const struct unit *punit, const struct city *pcity,
6039 const struct city *citymode,
6040 const struct unit_type *putype)
6041{
6042 int tileno, dir;
6045 struct terrain *tterrain_near[8];
6046 struct terrain *pterrain = nullptr;
6047 struct drawn_sprite *save_sprs = sprs;
6048 struct player *owner = nullptr;
6049 /* Unit drawing is disabled when the view options are turned off,
6050 * but only where we're drawing on the mapview. */
6051 bool do_draw_unit = (punit != nullptr && (gui_options.draw_units
6052 || ptile == nullptr
6054 && unit_is_in_focus(punit))));
6055 bool flagless = (do_draw_unit
6058 && ((do_draw_unit && !flagless)
6059 || (pcity != nullptr && gui_options.draw_cities)
6060 || (ptile != nullptr && !gui_options.draw_terrain)));
6061
6062 if (citymode) {
6063 int count = 0, i, cx, cy;
6064 const struct tile *const *tiles = nullptr;
6065 bool valid = FALSE;
6066
6067 if (ptile) {
6068 tiles = &ptile;
6069 count = 1;
6070 } else if (pcorner) {
6071 tiles = pcorner->tile;
6072 count = NUM_CORNER_TILES;
6073 } else if (pedge) {
6074 tiles = pedge->tile;
6075 count = NUM_EDGE_TILES;
6076 }
6077
6078 for (i = 0; i < count; i++) {
6079 if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
6080 valid = TRUE;
6081 break;
6082 }
6083 }
6084 if (!valid) {
6085 return 0;
6086 }
6087 }
6088
6089 if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
6090 textras = *tile_extras(ptile);
6091 pterrain = tile_terrain(ptile);
6092
6093 if (pterrain != nullptr) {
6094 if (layer == LAYER_TERRAIN1
6095 || layer == LAYER_TERRAIN2
6096 || layer == LAYER_TERRAIN3
6097 || layer == LAYER_WATER
6098 || layer == LAYER_ROADS) {
6099 build_tile_data(ptile, pterrain, tterrain_near, textras_near);
6100 }
6101 } else {
6102 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
6103 TILE_XY(ptile));
6104 }
6105 } else {
6107 }
6108
6109 switch (layer) {
6110 case LAYER_BACKGROUND:
6111 /* Set up background color. */
6113 if (do_draw_unit && !flagless) {
6115 } else if (pcity != nullptr && gui_options.draw_cities) {
6117 }
6118 }
6119 if (owner != nullptr) {
6121 } else if (ptile != nullptr && !gui_options.draw_terrain) {
6123 }
6124 break;
6125
6126 case LAYER_TERRAIN1:
6127 if (pterrain != nullptr && gui_options.draw_terrain && !solid_bg) {
6128 sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
6129 }
6130 break;
6131
6132 case LAYER_DARKNESS:
6133 if (pterrain != nullptr && gui_options.draw_terrain && !solid_bg) {
6135 }
6136 break;
6137
6138 case LAYER_TERRAIN2:
6139 if (pterrain != nullptr && gui_options.draw_terrain && !solid_bg) {
6140 sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
6141 }
6142 break;
6143
6144 case LAYER_TERRAIN3:
6145 if (pterrain != nullptr && gui_options.draw_terrain && !solid_bg) {
6147 sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
6148 }
6149 break;
6150
6151 case LAYER_WATER:
6152 if (pterrain != nullptr) {
6154 && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
6155 for (dir = 0; dir < t->num_cardinal_tileset_dirs; dir++) {
6156 int didx = t->cardinal_tileset_dirs[dir];
6157
6160 int idx = extra_index(priver);
6161
6162 if (BV_ISSET(textras_near[didx], idx)) {
6164 }
6165 }
6167 }
6168 }
6169
6171 pcity);
6172
6176 int idx = extra_index(priver);
6177
6178 if (BV_ISSET(textras, idx)) {
6179 int i;
6180
6181 /* Draw rivers on top of irrigation. */
6182 tileno = 0;
6183 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
6185
6187 tileno |= 1 << i;
6188 } else {
6190
6191 if (proad != nullptr) {
6192 extra_type_list_iterate(proad->integrators, iextra) {
6194 tileno |= 1 << i;
6195 }
6197 }
6198 }
6199 }
6200
6202 }
6203 }
6205 }
6206 }
6207 break;
6208
6209 case LAYER_ROADS:
6210 if (pterrain != nullptr) {
6212 if (is_extra_drawing_enabled(pextra)) {
6213 sprs += fill_road_sprite_array(t, pextra, sprs,
6216 }
6219 if (is_extra_drawing_enabled(pextra)) {
6220 sprs += fill_road_sprite_array(t, pextra, sprs,
6223 }
6226 if (is_extra_drawing_enabled(pextra)) {
6227 sprs += fill_road_sprite_array(t, pextra, sprs,
6230 }
6232 }
6233 break;
6234
6235 case LAYER_SPECIAL1:
6236 if (pterrain != nullptr) {
6237 if (ptile) {
6239 if (tile_has_extra(ptile, pextra)
6240 && is_extra_drawing_enabled(pextra)
6241 && t->sprites.extras[extra_index(pextra)].u.bmf.background != nullptr) {
6242 bool hidden = FALSE;
6243
6244 extra_type_list_iterate(pextra->hiders, phider) {
6246 hidden = TRUE;
6247 break;
6248 }
6250
6251 if (!hidden) {
6253 }
6254 }
6256 }
6257
6259 if (BV_ISSET(textras, extra_index(pextra))
6260 && is_extra_drawing_enabled(pextra)) {
6261 bool hidden = FALSE;
6262
6263 extra_type_list_iterate(pextra->hiders, phider) {
6265 hidden = TRUE;
6266 break;
6267 }
6269
6270 if (!hidden) {
6272 }
6273 }
6275 }
6276 break;
6277
6278 case LAYER_GRID1:
6279 if (t->type == TS_ISOMETRIC) {
6281 punit, pcity, citymode);
6282 }
6283 break;
6284
6285 case LAYER_CITY1:
6286 /* City. Some city sprites are drawn later. */
6287 if (pcity && gui_options.draw_cities) {
6289 struct sprite *spr = get_city_flag_sprite(t, pcity);
6290 struct area_rect flag_rect;
6291
6293
6297 flag_rect.w, flag_rect.h);
6298 }
6299 /* For iso-view the city.wall graphics include the full city, whereas
6300 * for non-iso view they are an overlay on top of the base city
6301 * graphic. */
6302 if (t->type == TS_OVERHEAD || pcity->client.walls <= 0) {
6306 }
6307 if (t->type == TS_ISOMETRIC && pcity->client.walls > 0) {
6308 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
6309 struct anim *anim = nullptr;
6310
6311 if (cspr != nullptr) {
6313 }
6314 if (anim == nullptr) {
6316 if (cspr != nullptr) {
6318 }
6319 }
6320
6321 if (anim != nullptr) {
6325 }
6326 }
6331 }
6332 if (t->type == TS_OVERHEAD && pcity->client.walls > 0) {
6333 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
6334 struct anim *anim = nullptr;
6335
6336 if (cspr != nullptr) {
6338 }
6339 if (anim == nullptr) {
6341 if (cspr != nullptr) {
6343 }
6344 }
6345
6346 if (anim != nullptr) {
6348 }
6349 }
6350 if (pcity->client.unhappy) {
6352 }
6353 }
6354 break;
6355
6356 case LAYER_SPECIAL2:
6357 if (pterrain != nullptr) {
6358 if (ptile) {
6360 if (tile_has_extra(ptile, pextra)
6361 && is_extra_drawing_enabled(pextra)
6362 && t->sprites.extras[extra_index(pextra)].u.bmf.middleground != nullptr) {
6363 bool hidden = FALSE;
6364
6365 extra_type_list_iterate(pextra->hiders, phider) {
6367 hidden = TRUE;
6368 break;
6369 }
6371
6372 if (!hidden) {
6374 }
6375 }
6377 }
6378
6380 if (BV_ISSET(textras, extra_index(pextra))
6381 && is_extra_drawing_enabled(pextra)) {
6382 bool hidden = FALSE;
6383
6384 extra_type_list_iterate(pextra->hiders, phider) {
6386 hidden = TRUE;
6387 break;
6388 }
6390
6391 if (!hidden) {
6393 }
6394 }
6396 }
6397 break;
6398
6399 case LAYER_UNIT:
6400 case LAYER_FOCUS_UNIT:
6401 if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
6402 int stack_count = ptile ? unit_list_size(ptile->units) : 0;
6403 bool backdrop = !pcity;
6404
6405 if (ptile && unit_is_in_focus(punit)
6406 && t->sprites.unit.select != nullptr) {
6407 /* Special case for drawing the selection rectangle. The blinking
6408 * unit is handled separately, inside get_drawable_unit(). */
6409 ADD_ANIM_SPRITE(t->sprites.unit.select, TRUE,
6411 }
6412
6413 /* Load more stack number sprites if needed. no_more_stack_sprites guard
6414 * that we don't retry over and over again for every stack,
6415 * when it's not working. */
6416 if (t->sprites.unit.num_stack_sprites < stack_count
6417 && !t->sprites.unit.no_more_stack_sprites) {
6418 t->sprites.unit.stack = fc_realloc(t->sprites.unit.stack,
6419 stack_count * sizeof(struct sprite *));
6420
6421 while (t->sprites.unit.num_stack_sprites < stack_count
6422 && !t->sprites.unit.no_more_stack_sprites) {
6423 struct sprite *spr = load_gfxnumber(t->sprites.unit.num_stack_sprites + 1);
6424
6425 if (spr != nullptr) {
6426 t->sprites.unit.stack[t->sprites.unit.num_stack_sprites++] = spr;
6427 } else {
6428 t->sprites.unit.no_more_stack_sprites = TRUE;
6429 t->sprites.unit.stack = fc_realloc(t->sprites.unit.stack,
6430 t->sprites.unit.num_stack_sprites * sizeof(struct sprite *));
6431 }
6432 }
6433 }
6434
6436 } else if (putype != nullptr && layer == LAYER_UNIT) {
6437 /* Only the sprite for the unit type. */
6438 /* FIXME: Shouldn't this still get activity and orientation of
6439 * the actual unit? */
6442 }
6443 break;
6444
6445 case LAYER_SPECIAL3:
6446 if (pterrain != nullptr) {
6447 if (ptile) {
6448 bool show_flag = FALSE;
6449 struct player *eowner = extra_owner(ptile);
6450
6452 if (is_extra_drawing_enabled(pextra)
6453 && tile_has_extra(ptile, pextra)
6454 && t->sprites.extras[extra_index(pextra)].u.bmf.foreground != nullptr) {
6455 bool hidden = FALSE;
6456
6457 extra_type_list_iterate(pextra->hiders, phider) {
6459 hidden = TRUE;
6460 break;
6461 }
6463
6464 if (!hidden) {
6465 if (t->sprites.extras[extra_index(pextra)].u.bmf.foreground != nullptr) {
6467 }
6468 }
6469 }
6471
6472 /* Show base flag. Not part of previous iteration as
6473 * "extras of ESTYLE_3_LAYER" != "bases" */
6474 if (eowner != nullptr) {
6476 if (tile_has_extra(ptile, pextra)) {
6477 bool hidden = FALSE;
6478
6479 extra_type_list_iterate(pextra->hiders, phider) {
6481 hidden = TRUE;
6482 break;
6483 }
6485
6486 if (!hidden) {
6487 show_flag = TRUE;
6488 }
6489 }
6491
6492 if (show_flag) {
6496 }
6497 }
6498 }
6499 }
6500 break;
6501
6502 case LAYER_FOG:
6504 break;
6505
6506 case LAYER_CITY2:
6507 /* City size. Drawing this under fog makes it hard to read. */
6509 bool warn = FALSE;
6510 unsigned int size = city_size_get(pcity);
6511
6515 if (10 <= size) {
6517 % 10], FALSE,
6520 if (100 <= size) {
6521 struct sprite *sprite
6522 = t->sprites.city.size_hundreds[(size / 100) % 10];
6523
6524 if (sprite != nullptr) {
6528 } else {
6529 warn = TRUE;
6530 }
6531 if (1000 <= size) {
6532 warn = TRUE;
6533 }
6534 }
6535 }
6536
6537 if (warn) {
6538 /* Warn only once by tileset. */
6539 static char last_reported[256] = "";
6540
6541 if (0 != strcmp(last_reported, t->name)) {
6542 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
6543 "such as %d. Size not displayed as expected."),
6544 t->name, size);
6546 }
6547 }
6548 }
6549 break;
6550
6551 case LAYER_GRID2:
6552 if (t->type == TS_OVERHEAD) {
6554 punit, pcity, citymode);
6555 }
6556 break;
6557
6558 case LAYER_OVERLAYS:
6560 if (mapdeco_is_crosshair_set(ptile)) {
6562 }
6563 break;
6564
6565 case LAYER_CITYBAR:
6566 case LAYER_TILELABEL:
6567 /* Nothing. This is just a placeholder. */
6568 break;
6569
6570 case LAYER_GOTO:
6571 if (ptile && goto_is_active()) {
6573 }
6574 break;
6575
6576 case LAYER_WORKERTASK:
6577 if (citymode != nullptr && ptile != nullptr) {
6579 if (ptask->ptile == ptile) {
6580 switch (ptask->act) {
6581 case ACTIVITY_MINE:
6582 if (ptask->tgt == nullptr) {
6583 ADD_SPRITE(t->sprites.unit.plant,
6586 } else {
6590 }
6591 break;
6592 case ACTIVITY_PLANT:
6593 ADD_SPRITE(t->sprites.unit.plant,
6596 break;
6597 case ACTIVITY_IRRIGATE:
6598 if (ptask->tgt == nullptr) {
6599 ADD_SPRITE(t->sprites.unit.cultivate,
6602 } else {
6606 }
6607 break;
6608 case ACTIVITY_CULTIVATE:
6609 ADD_SPRITE(t->sprites.unit.cultivate,
6612 break;
6613 case ACTIVITY_GEN_ROAD:
6614 if (ptask->tgt != nullptr) {
6618 }
6619 break;
6620 case ACTIVITY_TRANSFORM:
6621 ADD_SPRITE(t->sprites.unit.transform,
6624 break;
6625 case ACTIVITY_CLEAN:
6626 if (ptask->tgt != nullptr) {
6630 }
6631 break;
6632 default:
6633 break;
6634 }
6635 }
6637 }
6638 break;
6639
6640 case LAYER_EDITOR:
6641 if (ptile && editor_is_active()) {
6642 if (editor_tile_is_selected(ptile)) {
6645 }
6646
6647 if (map_startpos_get(ptile) != nullptr) {
6648 /* FIXME: Use a more representative sprite. */
6650 }
6651 }
6652 break;
6653
6654 case LAYER_INFRAWORK:
6655 if (ptile != nullptr) {
6656 if (ptile->placing != nullptr) {
6657 const int id = extra_index(ptile->placing);
6658
6659 if (t->sprites.extras[id].activity != nullptr) {
6663 }
6664 }
6665 if (client_infratile() == ptile) {
6667 }
6668 }
6669 break;
6670
6671 case LAYER_COUNT:
6673 break;
6674 }
6675
6676 return sprs - save_sprs;
6677}
6678
6679/************************************************************************/
6683void tileset_setup_city_tiles(struct tileset *t, int style)
6684{
6685 const char *style_name = city_style_rule_name(style);
6686
6687 if (style == game.control.num_city_styles - 1) {
6688 int i;
6689
6690 /* Free old sprites */
6692
6693 for (i = 0; i < NUM_WALL_TYPES; i++) {
6695 t->sprites.city.wall[i] = nullptr;
6696 }
6698 t->sprites.city.single_wall = nullptr;
6699
6701
6702 t->sprites.city.tile = load_city_sprite(t, "city");
6703
6704 for (i = 0; i < NUM_WALL_TYPES; i++) {
6705 char buffer[256];
6706
6707 fc_snprintf(buffer, sizeof(buffer), "bldg_%d", i);
6708 t->sprites.city.wall[i] = load_city_sprite(t, buffer);
6709 }
6710 t->sprites.city.single_wall = load_city_sprite(t, "wall");
6711
6712 t->sprites.city.occupied = load_city_sprite(t, "occupied");
6713 }
6714
6716 &t->sprites.style_citizen_sets.sets[style],
6717 city_styles[style].citizens_graphic,
6718 style_name, FALSE);
6721 &t->sprites.style_citizen_sets.sets[style],
6722 sp,
6723 city_styles[style].citizens_graphic,
6724 style_name, FALSE);
6726
6727 if (style == game.control.num_city_styles - 1) {
6728 for (style = 0; style < game.control.num_city_styles; style++) {
6729 if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
6731 _("City style \"%s\": no city graphics."),
6732 city_style_rule_name(style));
6733 }
6734 if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
6736 _("City style \"%s\": no occupied graphics."),
6737 city_style_rule_name(style));
6738 }
6739 }
6740 }
6741}
6742
6743/************************************************************************/
6749{
6750 if (t->sprites.unit.select != nullptr) {
6751 return 0.1;
6752 } else {
6753 return 0.5;
6754 }
6755}
6756
6757/************************************************************************/
6762{
6763 if (t->sprites.unit.select != nullptr) {
6764 t->sprites.unit.select->time = 0;
6765 } else {
6767 }
6768}
6769
6770/************************************************************************/
6774{
6776}
6777
6778/************************************************************************/
6783{
6784 if (t->sprites.unit.select != nullptr) {
6785 anim_advance_time(t->sprites.unit.select);
6786 } else {
6788 }
6789}
6790
6791/************************************************************************/
6801
6802/************************************************************************/
6805struct unit *get_drawable_unit(const struct tileset *t,
6806 struct tile *ptile,
6807 const struct city *citymode)
6808{
6809 struct unit *punit = find_visible_unit(ptile);
6810
6811 if (punit == nullptr) {
6812 return nullptr;
6813 }
6814
6816 return nullptr;
6817 }
6818
6820 || t->sprites.unit.select != nullptr || focus_unit_state) {
6821 return punit;
6822 } else {
6823 return nullptr;
6824 }
6825}
6826
6827/************************************************************************/
6831static void unload_all_sprites(struct tileset *t)
6832{
6833 if (t->sprite_hash != nullptr) {
6835 while (ss->ref_count > 0) {
6837 }
6839 }
6840}
6841
6842/************************************************************************/
6845static void free_all_anims(struct tileset *t)
6846{
6847 if (t->anim_hash != nullptr) {
6848 anim_hash_iterate(t->anim_hash, tag, anim) {
6849 (void)tag;
6850 anim_free(anim);
6852 }
6853}
6854
6855/************************************************************************/
6859{
6860 int i;
6861
6862 log_debug("tileset_free_tiles()");
6863
6865
6867 t->sprites.city.tile = nullptr;
6868
6869 for (i = 0; i < NUM_WALL_TYPES; i++) {
6871 t->sprites.city.wall[i] = nullptr;
6872 }
6874 t->sprites.city.single_wall = nullptr;
6875
6877 t->sprites.city.occupied = nullptr;
6878
6879 if (t->sprite_hash) {
6881 t->sprite_hash = nullptr;
6882 }
6883
6884 if (t->sprites.style_citizen_sets.sets != nullptr) {
6886 t->sprites.style_citizen_sets.sets = nullptr;
6887 }
6888
6891 if (ss->file) {
6892 free(ss->file);
6893 }
6894
6895 fc_assert(ss->sprite == nullptr);
6896
6897 free(ss);
6899
6902 free(sf->file_name);
6903 if (sf->big_sprite) {
6904 free_sprite(sf->big_sprite);
6905 sf->big_sprite = nullptr;
6906 }
6907 free(sf);
6909
6914
6919
6920 if (t->sprites.tx.fullfog) {
6921 free(t->sprites.tx.fullfog);
6922 t->sprites.tx.fullfog = nullptr;
6923 }
6924
6930
6931 /* Index 0 is 'occupied' or 'default' stack sprite */
6932 for (i = 1; i < t->sprites.unit.num_stack_sprites - 1; i++) {
6933 free_sprite(t->sprites.unit.stack[i]);
6934 }
6935 t->sprites.unit.num_stack_sprites = 0;
6936 if (t->sprites.unit.stack != nullptr) {
6937 free(t->sprites.unit.stack);
6938 t->sprites.unit.stack = nullptr;
6939 }
6940
6941 free_all_anims(t);
6942 t->sprites.unit.select = nullptr;
6943 t->sprites.unit.action_decision_want = nullptr;
6944
6945 if (t->anim_hash) {
6947 t->anim_hash = nullptr;
6948 }
6949
6951}
6952
6953/************************************************************************/
6956struct sprite *get_spaceship_sprite(const struct tileset *t,
6957 enum spaceship_part part)
6958{
6959 return t->sprites.spaceship[part];
6960}
6961
6962/************************************************************************/
6965static inline const struct citizen_graphic *
6968{
6969 fc_assert_ret_val(set != nullptr, nullptr);
6970
6971 if (type < CITIZEN_SPECIALIST) {
6972 fc_assert_ret_val(type >= 0, nullptr);
6973
6974 return &set->citizen[type];
6975 } else {
6977
6978 return &set->specialist[type - CITIZEN_SPECIALIST];
6979 }
6980}
6981
6982/************************************************************************/
6989struct sprite *get_citizen_sprite(const struct tileset *t,
6991 int citizen_index,
6992 const struct city *pcity)
6993{
6994 const struct citizen_graphic *graphic = nullptr;
6996
6997 if (pcity != nullptr) {
6998 int style = style_of_city(pcity);
6999
7001
7003 type);
7004
7005 gfx_index += pcity->client.first_citizen_index;
7006 }
7007
7008 if (graphic == nullptr || graphic->count == 0) {
7009 /* Fall back to default sprites */
7011 }
7012
7013 if (graphic->count == 0) {
7014 return nullptr;
7015 }
7016
7017 return graphic->sprite[gfx_index % graphic->count];
7018}
7019
7020/************************************************************************/
7023struct sprite *get_nation_flag_sprite(const struct tileset *t,
7024 const struct nation_type *pnation)
7025{
7026 return t->sprites.nation_flag.p[nation_index(pnation)];
7027}
7028
7029/************************************************************************/
7033 const struct nation_type *pnation)
7034{
7035 return t->sprites.nation_shield.p[nation_index(pnation)];
7036}
7037
7038/************************************************************************/
7041struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
7042{
7043 fc_assert_ret_val(0 <= tech && tech < advance_count(), nullptr);
7044
7045 return t->sprites.tech[tech];
7046}
7047
7048/************************************************************************/
7051struct sprite *get_building_sprite(const struct tileset *t,
7052 const struct impr_type *pimprove)
7053{
7054 fc_assert_ret_val(pimprove != nullptr, nullptr);
7055
7056 return t->sprites.building[improvement_index(pimprove)];
7057}
7058
7059/************************************************************************/
7062struct sprite *get_government_sprite(const struct tileset *t,
7063 const struct government *gov)
7064{
7065 fc_assert_ret_val(gov != nullptr, nullptr);
7066
7067 return t->sprites.government[government_index(gov)];
7068}
7069
7070/************************************************************************/
7075struct sprite *get_unittype_sprite(const struct tileset *t,
7076 const struct unit_type *punittype,
7077 enum unit_activity activity,
7078 enum direction8 facing)
7079{
7080 int uidx = utype_index(punittype);
7081 bool icon = !direction8_is_valid(facing);
7082
7083 if (activity >= ACTIVITY_LAST) {
7084 activity = ACTIVITY_IDLE;
7085 }
7086
7087 fc_assert_ret_val(punittype != nullptr, nullptr);
7088
7089 if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
7090 facing = t->unit_default_orientation;
7091 /* May not have been specified, but it only matters if we don't
7092 * turn out to have an icon sprite */
7093 }
7094
7095 if (t->sprites.units.icon[uidx][activity] != nullptr
7096 && (icon || t->sprites.units.facing[uidx][facing][activity] == nullptr)) {
7097 /* Has icon sprite, and we prefer to (or must) use it */
7098 if (icon) {
7099 return t->sprites.units.icon[uidx][activity]->sprites[0];
7100 } else {
7101 return anim_get_current_frame(t->sprites.units.icon[uidx][activity]);
7102 }
7103 } else if (t->sprites.units.icon[uidx][ACTIVITY_IDLE] != nullptr
7104 && (icon
7105 || t->sprites.units.facing[uidx][facing][ACTIVITY_IDLE] == nullptr)) {
7106 /* Has icon sprite, and we prefer to (or must) use it */
7107 if (icon) {
7108 return t->sprites.units.icon[uidx][ACTIVITY_IDLE]->sprites[0];
7109 } else {
7111 }
7112 } else {
7113 /* We should have a valid orientation by now. Failure to have either
7114 * an icon sprite or default orientation should have been caught at
7115 * tileset load. */
7116 fc_assert_ret_val(direction8_is_valid(facing), nullptr);
7117
7118 if (t->sprites.units.facing[uidx][facing][activity] == nullptr) {
7120 }
7121
7122 return anim_get_current_frame(t->sprites.units.facing[uidx][facing][activity]);
7123 }
7124}
7125
7126/************************************************************************/
7129struct sprite *get_sample_city_sprite(const struct tileset *t,
7130 int style_idx)
7131{
7132 int num_thresholds
7133 = t->sprites.city.tile->styles[style_idx].land_num_thresholds;
7134
7135 if (num_thresholds == 0) {
7136 return nullptr;
7137 } else {
7138 return (t->sprites.city.tile->styles[style_idx]
7139 .land_thresholds[num_thresholds - 1].cst->sprites[0]);
7140 }
7141}
7142
7143/************************************************************************/
7146struct sprite *get_arrow_sprite(const struct tileset *t,
7147 enum arrow_type arrow)
7148{
7149 fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, nullptr);
7150
7151 return t->sprites.arrow[arrow];
7152}
7153
7154/************************************************************************/
7158{
7159 switch (otype) {
7160 case O_SCIENCE:
7161 return t->sprites.tax_science;
7162 case O_GOLD:
7163 return t->sprites.tax_gold;
7164 case O_LUXURY:
7165 return t->sprites.tax_luxury;
7166 case O_TRADE:
7167 case O_FOOD:
7168 case O_SHIELD:
7169 case O_LAST:
7170 break;
7171 }
7172
7173 return nullptr;
7174}
7175
7176/************************************************************************/
7179struct sprite *get_event_sprite(const struct tileset *t, enum event_type event)
7180{
7181 return t->sprites.events[event];
7182}
7183
7184/************************************************************************/
7188struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
7189{
7190 return t->sprites.treaty_thumb[on_off ? 1 : 0];
7191}
7192
7193/************************************************************************/
7198 tileset *t)
7199{
7200 return &t->sprites.explode.unit;
7201}
7202
7203/************************************************************************/
7209{
7210 return t->sprites.explode.nuke;
7211}
7212
7213/************************************************************************/
7216const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
7217{
7219 return &t->sprites.citybar;
7220 } else {
7221 return nullptr;
7222 }
7223}
7224
7225/************************************************************************/
7228const struct editor_sprites *get_editor_sprites(const struct tileset *t)
7229{
7230 return &t->sprites.editor;
7231}
7232
7233/************************************************************************/
7239struct sprite *get_cursor_sprite(const struct tileset *t,
7240 enum cursor_type cursor,
7241 int *hot_x, int *hot_y, int frame)
7242{
7243 *hot_x = t->sprites.cursor[cursor].hot_x;
7244 *hot_y = t->sprites.cursor[cursor].hot_y;
7245
7246 return t->sprites.cursor[cursor].frame[frame];
7247}
7248
7249/************************************************************************/
7258struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
7259{
7260 return t->sprites.icon[icon];
7261}
7262
7263/************************************************************************/
7270{
7271 return t->sprites.user.attention;
7272}
7273
7274/************************************************************************/
7278struct sprite *get_indicator_sprite(const struct tileset *t,
7279 enum indicator_type indicator,
7280 int idx)
7281{
7282 idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
7283
7284 fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, nullptr);
7285
7286 return t->sprites.indicator[indicator][idx];
7287}
7288
7289/************************************************************************/
7296 const struct unit *punit,
7297 int happy_cost)
7298{
7299 const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
7300
7301 if (unhappy > 0) {
7302 return t->sprites.upkeep.unhappy[unhappy - 1];
7303 } else {
7304 return nullptr;
7305 }
7306}
7307
7308/************************************************************************/
7314struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
7316 const struct unit *punit,
7317 const int *upkeep_cost)
7318{
7319 const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES + 1);
7320
7321 if (upkeep > 0) {
7322 return t->sprites.upkeep.output[otype][upkeep - 1];
7323 } else {
7324 return nullptr;
7325 }
7326}
7327
7328/************************************************************************/
7332struct sprite *get_basic_fog_sprite(const struct tileset *t)
7333{
7334 return t->sprites.tx.fog;
7335}
7336
7337/************************************************************************/
7340struct color_system *get_color_system(const struct tileset *t)
7341{
7342 return t->color_system;
7343}
7344
7345/************************************************************************/
7349{
7350 char *default_theme_name = nullptr;
7351 size_t default_theme_name_sz = 0;
7352 int i;
7353
7354 switch (get_gui_type()) {
7355 case GUI_GTK3_22:
7358 break;
7359 case GUI_GTK4:
7362 break;
7363 case GUI_GTK5:
7366 break;
7367 case GUI_SDL2:
7370 break;
7371 case GUI_SDL3:
7374 break;
7375 case GUI_STUB:
7376 case GUI_QT:
7377 case GUI_SDL:
7378 case GUI_WEB:
7379 case GUI_GTK2:
7380 case GUI_GTK3:
7381 break;
7382 }
7383
7384 if (default_theme_name == nullptr || 0 == default_theme_name_sz) {
7385 /* Theme is not supported by this client. */
7386 return;
7387 }
7388
7389 for (i = 0; i < t->num_preferred_themes; i++) {
7392 log_debug("trying theme \"%s\".", t->preferred_themes[i]);
7393 if (load_theme(t->preferred_themes[i])) {
7396 return;
7397 }
7398 }
7399 }
7400 }
7401 log_verbose("The tileset doesn't specify preferred themes or none of its "
7402 "preferred themes can be used. Using system default.");
7404}
7405
7406/************************************************************************/
7409void tileset_init(struct tileset *t)
7410{
7411 int wi;
7412
7413 /* We currently have no city sprites loaded. */
7414 t->sprites.city.tile = nullptr;
7415
7416 for (wi = 0; wi < NUM_WALL_TYPES; wi++) {
7417 t->sprites.city.wall[wi] = nullptr;
7418 }
7419 t->sprites.city.single_wall = nullptr;
7420
7421 t->sprites.city.occupied = nullptr;
7422
7423 t->sprites.background.color = nullptr;
7424 t->sprites.background.graphic = nullptr;
7425
7426 player_slots_iterate(pslot) {
7427 int edge, j, id = player_slot_index(pslot);
7428
7429 for (edge = 0; edge < EDGE_COUNT; edge++) {
7430 for (j = 0; j < 2; j++) {
7431 t->sprites.player[id].grid_borders[edge][j] = nullptr;
7432 }
7433 }
7434
7435 t->sprites.player[id].color = nullptr;
7436 t->sprites.player[id].background = nullptr;
7438
7439 t->max_upkeep_height = 0;
7440}
7441
7442/************************************************************************/
7451 struct drawn_sprite *sprs,
7452 int layer,
7453 struct terrain *pterrain)
7454{
7455 struct drawn_sprite *save_sprs = sprs;
7456 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
7457
7458 struct terrain *tterrain_near[8];
7460
7461 struct tile dummy_tile; /* :( */
7462
7463 int i;
7464
7465
7466 memset(&dummy_tile, 0, sizeof(struct tile));
7467
7468 for (i = 0; i < 8; i++) {
7469 tterrain_near[i] = pterrain;
7471 }
7472
7473 i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
7475 pterrain, tterrain_near, draw);
7476
7477 return sprs - save_sprs;
7478}
7479
7480/************************************************************************/
7484 struct drawn_sprite *sprs,
7485 const struct extra_type *pextra)
7486{
7487 int idx = extra_index(pextra);
7488 struct drawn_sprite *saved_sprs = sprs;
7489
7490 switch (t->sprites.extras[idx].extrastyle) {
7491 case ESTYLE_SINGLE1:
7492 case ESTYLE_SINGLE2:
7494 break;
7495 case ESTYLE_CARDINALS:
7497 break;
7501 case ESTYLE_RIVER:
7502 return fill_basic_road_sprite_array(t, sprs, pextra);
7503 case ESTYLE_3LAYER:
7504 return fill_basic_base_sprite_array(t, sprs, pextra);
7505 case ESTYLE_COUNT:
7507 break;
7508 }
7509
7510 return sprs - saved_sprs;
7511}
7512
7513/************************************************************************/
7519 struct drawn_sprite *sprs,
7520 const struct extra_type *pextra)
7521{
7522 struct drawn_sprite *saved_sprs = sprs;
7523 int idx;
7524 int i;
7525 enum extrastyle_id extrastyle;
7526
7527 if (!t || !sprs || !pextra) {
7528 return 0;
7529 }
7530
7531 idx = extra_index(pextra);
7532
7533 if (!(0 <= idx && idx < game.control.num_extra_types)) {
7534 return 0;
7535 }
7536
7537 extrastyle = t->sprites.extras[idx].extrastyle;
7538
7539 if (extrastyle == ESTYLE_RIVER) {
7541 } else {
7542 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
7543 if (!t->valid_tileset_dirs[i]) {
7544 continue;
7545 }
7546 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
7548 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
7549 if ((i % 2) == 0) {
7550 ADD_FRAME0_SIMPLE(t->sprites.extras[idx].u.road.ru.combo.even[1 << (i / 2)]);
7551 }
7552 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
7553 ADD_FRAME0_SIMPLE(t->sprites.extras[idx].u.road.ru.total[1 << i]);
7554 }
7555 }
7556 }
7557
7558 return sprs - saved_sprs;
7559}
7560
7561/************************************************************************/
7567 struct drawn_sprite *sprs,
7568 const struct extra_type *pextra)
7569{
7570 struct drawn_sprite *saved_sprs = sprs;
7571 int idx;
7572
7573 if (!t || !sprs || !pextra) {
7574 return 0;
7575 }
7576
7577 idx = extra_index(pextra);
7578
7579 if (!(0 <= idx && idx < game.control.num_extra_types)) {
7580 return 0;
7581 }
7582
7583#define ADD_FRAME0_IF_NOT_NULL(x) do {\
7584 if ((x) != nullptr) {\
7585 ADD_FRAME0_FULL(x);\
7586 }\
7587} while (FALSE)
7588
7589 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
7593
7594#undef ADD_FRAME0_IF_NOT_NULL
7595
7596 return sprs - saved_sprs;
7597}
7598
7599/************************************************************************/
7602enum mapview_layer tileset_get_layer(const struct tileset *t, int n)
7603{
7605
7606 return t->layer_order[n];
7607}
7608
7609/************************************************************************/
7613 enum layer_category cat)
7614{
7615 switch (layer) {
7616 case LAYER_BACKGROUND:
7617 case LAYER_TERRAIN1:
7618 case LAYER_DARKNESS:
7619 case LAYER_TERRAIN2:
7620 case LAYER_TERRAIN3:
7621 case LAYER_WATER:
7622 case LAYER_ROADS:
7623 case LAYER_SPECIAL1:
7624 case LAYER_SPECIAL2:
7625 case LAYER_SPECIAL3:
7627 case LAYER_CITY1:
7628 case LAYER_CITY2:
7629 return cat == LAYER_CATEGORY_CITY;
7630 case LAYER_UNIT:
7631 case LAYER_FOCUS_UNIT:
7632 return cat == LAYER_CATEGORY_UNIT;
7633 case LAYER_GRID1:
7634 case LAYER_FOG:
7635 case LAYER_GRID2:
7636 case LAYER_OVERLAYS:
7637 case LAYER_TILELABEL:
7638 case LAYER_CITYBAR:
7639 case LAYER_GOTO:
7640 case LAYER_WORKERTASK:
7641 case LAYER_EDITOR:
7642 case LAYER_INFRAWORK:
7643 return FALSE;
7644 case LAYER_COUNT:
7645 break; /* and fail below */
7646 }
7647
7648 fc_assert_msg(FALSE, "Unknown layer category: %d", cat);
7649 return FALSE;
7650}
7651
7652/************************************************************************/
7655void tileset_player_init(struct tileset *t, struct player *pplayer)
7656{
7657 int plrid, i, j;
7658 struct sprite *color;
7659
7660 fc_assert_ret(pplayer != nullptr);
7661
7662 plrid = player_index(pplayer);
7663 fc_assert_ret(plrid >= 0);
7665
7666 /* Free all data before recreating it. */
7668
7669 if (player_has_color(pplayer)) {
7671 = create_plr_sprite(get_player_color(t, pplayer));
7672 } else {
7673 /* XXX: if player hasn't been assigned a color, perhaps there's no
7674 * point proceeding with an arbitrary color; this should only happen
7675 * in pregame. Probably blank sprites would be better. */
7676
7677 fc_assert_ret(t->sprites.background.color != nullptr);
7678
7679 color = t->sprites.background.color;
7680 }
7681
7683 = crop_sprite(color, 0, 0,
7685 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
7686
7687 for (i = 0; i < EDGE_COUNT; i++) {
7688 for (j = 0; j < 2; j++) {
7689 struct sprite *s;
7690
7691 if (color && t->sprites.grid.borders[i][j]) {
7692 s = crop_sprite(color, 0, 0,
7694 t->sprites.grid.borders[i][j], 0, 0, 1.0f, FALSE);
7695 } else {
7696 s = t->sprites.grid.borders[i][j];
7697 }
7698 t->sprites.player[plrid].grid_borders[i][j] = s;
7699 }
7700 }
7701}
7702
7703/************************************************************************/
7706static void tileset_player_free(struct tileset *t, int plrid)
7707{
7708 int i, j;
7709
7710 fc_assert_ret(plrid >= 0);
7712
7713 if (t->sprites.player[plrid].color) {
7715 t->sprites.player[plrid].color = nullptr;
7716 }
7717 if (t->sprites.player[plrid].background) {
7719 t->sprites.player[plrid].background = nullptr;
7720 }
7721
7722 for (i = 0; i < EDGE_COUNT; i++) {
7723 for (j = 0; j < 2; j++) {
7724 if (t->sprites.player[plrid].grid_borders[i][j]) {
7726 t->sprites.player[plrid].grid_borders[i][j] = nullptr;
7727 }
7728 }
7729 }
7730}
7731
7732/************************************************************************/
7736{
7737 /* Free all data before recreating it. */
7739
7740 /* Generate background color */
7741 t->sprites.background.color
7743
7744 /* Chop up and build the background graphics. */
7745 t->sprites.background.graphic
7746 = crop_sprite(t->sprites.background.color, 0, 0,
7748 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
7749}
7750
7751/************************************************************************/
7755{
7756 if (t->sprites.background.color) {
7757 free_sprite(t->sprites.background.color);
7758 t->sprites.background.color = nullptr;
7759 }
7760
7761 if (t->sprites.background.graphic) {
7762 free_sprite(t->sprites.background.graphic);
7763 t->sprites.background.graphic = nullptr;
7764 }
7765}
7766
7767/************************************************************************/
7771{
7772 int i;
7773
7774 for (i = 0; i < ESTYLE_COUNT; i++) {
7775 if (t->style_lists[i] != nullptr) {
7778 }
7779 }
7780
7781 if (t->flagged_bases_list != nullptr) {
7784 }
7785
7786 if (t->sprites.style_citizen_sets.sets != nullptr) {
7788 }
7789
7792 * sizeof(t->sprites.style_citizen_sets.sets[0]));
7793}
7794
7795/************************************************************************/
7799{
7800 return !tileset_update;
7801}
7802
7803/************************************************************************/
7806const char *tileset_name_get(struct tileset *t)
7807{
7808 return t->given_name;
7809}
7810
7811/************************************************************************/
7814const char *tileset_version(struct tileset *t)
7815{
7816 return t->version;
7817}
7818
7819/************************************************************************/
7822const char *tileset_summary(struct tileset *t)
7823{
7824 return t->summary;
7825}
7826
7827/************************************************************************/
7830const char *tileset_description(struct tileset *t)
7831{
7832 return t->description;
7833}
7834
7835/************************************************************************/
7839{
7840 return t->for_ruleset;
7841}
7842
7843/************************************************************************/
7847{
7848 return t->ts_topo_idx;
7849}
7850
7851/************************************************************************/
7855{
7856 return t->svg_height;
7857}
7858
7859/************************************************************************/
7862struct sprite *load_popup_sprite(const char *tag)
7863{
7864 return load_sprite(tileset, tag, TRUE, TRUE, FALSE);
7865}
7866
7867/************************************************************************/
7870void unload_popup_sprite(const char *tag)
7871{
7872 unload_sprite(tileset, tag);
7873}
#define str
Definition astring.c:76
#define n
Definition astring.c:77
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int int int struct sprite *sprite struct canvas struct color * pcolor
Definition canvas_g.h:56
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
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
bool base_city_celebrating(const struct city *pcity)
Definition city.c:1690
const char * city_style_rule_name(const int style)
Definition city.c:1818
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
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:1540
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:281
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:264
static const struct city struct citystyle * city_styles
Definition city.c:84
int city_tile_output(const struct city *pcity, const struct tile *ptile, bool is_celebrating, Output_type_id otype)
Definition city.c:1336
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1509
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
citizen_category
Definition city.h:265
@ CITIZEN_LAST
Definition city.h:270
@ CITIZEN_SPECIALIST
Definition city.h:271
@ CITIZEN_ANGRY
Definition city.h:269
@ CITIZEN_HAPPY
Definition city.h:266
@ CITIZEN_CONTENT
Definition city.h:267
@ CITIZEN_UNHAPPY
Definition city.h:268
#define output_type_iterate(output)
Definition city.h:853
#define city_owner(_pcity_)
Definition city.h:564
#define MAX_CITY_SIZE
Definition city.h:104
#define output_type_iterate_end
Definition city.h:859
void generate_citydlg_dimensions(void)
struct civclient client
enum client_states client_state(void)
#define client_player()
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
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)
char * incite_cost
Definition comments.c:77
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:388
bool should_ask_server_for_actions(const struct unit *punit)
Definition control.c:339
struct unit_list * get_units_in_focus(void)
Definition control.c:177
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:834
static void road(QVariant data1, QVariant data2)
Definition dialogs.cpp:3314
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 struct unit struct city * pcity
Definition dialogs_g.h:77
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_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:842
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct req_context *other_context, enum effect_type effect_type)
Definition effects.c:744
enum event_type event
Definition events.c:82
static struct @25 events[]
const char * get_event_tag(enum event_type event)
Definition events.c:277
char * tag_name
Definition events.c:78
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1128
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
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:203
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:353
int extra_count(void)
Definition extras.c:153
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define extra_type_list_iterate_end
Definition extras.h:167
#define extra_road_get(_e_)
Definition extras.h:191
#define MAX_VET_LEVELS
Definition fc_types.h:49
#define DIR8_MAGIC_MAX
Definition fc_types.h:330
#define MAX_NUM_ITEMS
Definition fc_types.h:40
int Tech_type_id
Definition fc_types.h:238
#define SP_MAX
Definition fc_types.h:269
int Specialist_type_id
Definition fc_types.h:236
#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:68
@ O_SHIELD
Definition fc_types.h:103
@ O_FOOD
Definition fc_types.h:103
@ O_TRADE
Definition fc_types.h:103
@ O_SCIENCE
Definition fc_types.h:103
@ O_LUXURY
Definition fc_types.h:103
@ O_GOLD
Definition fc_types.h:103
@ O_LAST
Definition fc_types.h:103
@ BORDERS_DISABLED
Definition fc_types.h:732
enum output_type_id Output_type_id
Definition fc_types.h:239
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
bool goto_is_active(void)
Definition goto.c:1070
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:84
const char * government_rule_name(const struct government *pgovern)
Definition government.c:132
#define governments_iterate(NAME_pgov)
Definition government.h:136
#define G_LAST
Definition government.h:50
#define governments_iterate_end
Definition government.h:139
struct city * owner
Definition citydlg.c:226
void show_tileset_error(bool fatal, const char *tset_name, const char *msg)
Definition dialogs.c:1540
void tileset_type_set(enum ts_type type)
Definition graphics.c:53
enum gui_type get_gui_type(void)
Definition gui_main.c:2046
void dirty_all(void)
Definition mapview.c:456
void tileset_changed(void)
Definition mapview.c:782
GType type
Definition repodlgs.c:1313
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * create_sprite(int width, int height, struct color *pcolor)
Definition sprite.c:84
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, bool svgflag)
Definition sprite.c:170
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
struct client_properties gui_properties
void boot_help_texts(void)
Definition helpdata.c:768
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:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_fatal(message,...)
Definition log.h:101
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_base(level, message,...)
Definition log.h:95
log_level
Definition log.h:29
@ LOG_ERROR
Definition log.h:31
@ LOG_DEBUG
Definition log.h:35
@ LOG_NORMAL
Definition log.h:33
@ LOG_FATAL
Definition log.h:30
@ LOG_VERBOSE
Definition log.h:34
#define log_error(message,...)
Definition log.h:104
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:209
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:2047
enum direction8 dir_ccw(enum direction8 dir)
Definition map.c:1353
bool is_valid_dir(enum direction8 dir)
Definition map.c:1410
enum direction8 dir_cw(enum direction8 dir)
Definition map.c:1324
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
static int img_index(const int x, const int y, const struct img *pimg)
Definition mapimg.c:1997
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 view mapview
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)
void update_map_canvas(int canvas_x, int canvas_y, int width, int height)
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)
const char * modpack_tileset_target(const char *name)
Definition modpack.c:329
void modpack_tileset_cache_iterate(mrc_cb cb, void *data)
Definition modpack.c:360
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
#define SINGLE_MOVE
Definition movement.h:26
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_count(void)
Definition nation.c:503
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:461
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:495
#define nations_iterate_end
Definition nation.h:364
#define nations_iterate(NAME_pnation)
Definition nation.h:361
void option_set_default_ts(struct tileset *t)
Definition options.c:6937
const char * option_str_get(const struct option *poption)
Definition options.c:944
int option_get_cb_data(const struct option *poption)
Definition options.c:838
struct client_options gui_options
Definition options.c:71
int len
Definition packhand.c:129
bool player_in_city_map(const struct player *pplayer, const struct tile *ptile)
Definition player.c:1237
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
int player_index(const struct player *pplayer)
Definition player.c:818
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define player_slots_iterate(_pslot)
Definition player.h:538
#define player_slots_iterate_end
Definition player.h:542
#define fc_randomly(_seed, _size)
Definition rand.h:73
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:51
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
#define secfile_entry_ignore_by_path(_sfile_, _path_)
bool is_cardinal_only_road(const struct extra_type *pextra)
Definition road.c:490
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
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:110
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
size_t size
Definition specvec.h:72
struct sprite int int int int struct sprite * mask
Definition sprite_g.h:32
struct sprite int int y
Definition sprite_g.h:31
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
struct sprite int x
Definition sprite_g.h:31
crop_sprite
Definition sprite_g.h:30
struct sprite int int int int struct sprite int int float bool smooth get_sprite_dimensions
Definition sprite_g.h:36
int main(int argc, char *argv[])
static bool wall(char *str, bool check)
Definition stdinhand.c:1908
void strvec_append(struct strvec *psv, const char *string)
struct strvec * strvec_new(void)
struct sprite ** sprites
Definition tilespec.c:172
int time
Definition tilespec.c:170
bool show_always
Definition tilespec.c:173
int time_per_frame
Definition tilespec.c:171
int frames
Definition tilespec.c:169
struct sprite * sprite[MAX_NUM_CITIZEN_SPRITES]
Definition tilespec.c:233
struct citizen_graphic citizen[CITIZEN_LAST]
Definition tilespec.c:237
struct citizen_graphic specialist[SP_MAX]
Definition tilespec.c:238
struct city_sprite::@257 * styles
struct city_style_threshold * land_thresholds
Definition tilespec.c:218
int land_num_thresholds
Definition tilespec.c:217
int num_styles
Definition tilespec.c:220
struct anim * cst
Definition tilespec.c:212
Definition city.h:318
citizens size
Definition city.h:330
struct sprite_vector occupancy
Definition tilespec.h:339
struct civ_game::@32::@35 client
struct rgbcolor * plr_bg_color
Definition game.h:103
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
bool ruleset_ready
Definition game.h:119
int topology_id
Definition map_types.h:72
struct connection conn
Definition client_main.h:96
bool draw_native
Definition options.h:216
bool draw_specials
Definition options.h:208
bool draw_city_output
Definition options.h:195
char gui_sdl3_default_theme_name[512]
Definition options.h:442
bool draw_mines
Definition options.h:206
bool draw_borders
Definition options.h:215
bool draw_fortress_airbase
Definition options.h:207
bool draw_unit_stack_size
Definition options.h:219
bool draw_irrigation
Definition options.h:205
bool draw_terrain
Definition options.h:202
bool draw_units
Definition options.h:212
int default_topology
Definition options.h:123
bool draw_fog_of_war
Definition options.h:214
bool draw_unit_shields
Definition options.h:218
char gui_sdl2_default_theme_name[512]
Definition options.h:429
bool draw_cities
Definition options.h:211
bool draw_map_grid
Definition options.h:196
bool draw_focus_unit
Definition options.h:213
bool draw_paths
Definition options.h:204
bool draw_city_outlines
Definition options.h:194
bool draw_coastline
Definition options.h:203
bool draw_full_citybar
Definition options.h:217
bool draw_pollution
Definition options.h:210
char gui_gtk5_default_theme_name[512]
Definition options.h:382
char gui_gtk4_default_theme_name[512]
Definition options.h:342
char gui_gtk3_22_default_theme_name[512]
Definition options.h:302
bool solid_color_behind_units
Definition options.h:150
struct client_properties::@227 views
Definition colors.h:21
bool established
Definition connection.h:140
struct player * playing
Definition connection.h:151
int match_index[1+MAX_NUM_MATCH_WITH]
Definition tilespec.c:190
enum match_style match_style
Definition tilespec.c:189
enum sprite_type sprite_type
Definition tilespec.c:193
struct sprite_vector allocated
Definition tilespec.c:201
struct sprite * match[MAX_INDEX_CARDINAL]
Definition tilespec.c:196
struct sprite_vector base
Definition tilespec.c:195
struct sprite ** cells
Definition tilespec.c:197
bool is_reversed
Definition tilespec.c:204
struct sprite * blend[4]
Definition tilespec.c:208
struct drawing_data::drawing_layer layer[MAX_NUM_LAYERS]
struct sprite * blender
Definition tilespec.c:207
char * name
Definition tilespec.c:179
char rmact_gfx[MAX_LEN_NAME]
Definition extras.h:102
char act_gfx_alt[MAX_LEN_NAME]
Definition extras.h:100
struct extra_type_list * hiders
Definition extras.h:144
char rmact_gfx_alt[MAX_LEN_NAME]
Definition extras.h:103
struct road_type * road
Definition extras.h:155
char rmact_gfx_alt2[MAX_LEN_NAME]
Definition extras.h:104
char graphic_alt[MAX_LEN_NAME]
Definition extras.h:98
char activity_gfx[MAX_LEN_NAME]
Definition extras.h:99
char act_gfx_alt2[MAX_LEN_NAME]
Definition extras.h:101
char graphic_str[MAX_LEN_NAME]
Definition extras.h:97
char graphic_alt[MAX_LEN_NAME]
Definition government.h:60
char graphic_str[MAX_LEN_NAME]
Definition government.h:59
char graphic_str[MAX_LEN_NAME]
Definition improvement.h:55
char graphic_alt2[MAX_LEN_NAME]
Definition improvement.h:57
char graphic_alt[MAX_LEN_NAME]
Definition improvement.h:56
struct anim * dir[8]
Definition tilespec.c:384
struct sprite * graphic
Definition tilespec.c:414
struct sprite * tax_gold
Definition tilespec.c:257
struct sprite * government[G_LAST]
Definition tilespec.c:269
struct anim * total[MAX_INDEX_VALID]
Definition tilespec.c:392
struct sprite_vector nation_shield
Definition tilespec.c:277
struct citizen_set default_citizens
Definition tilespec.c:279
struct sprite * loaded
Definition tilespec.c:311
struct sprite * output[O_LAST][MAX_NUM_UPKEEP_SPRITES]
Definition tilespec.c:323
struct sprite ** stack
Definition tilespec.c:310
struct anim * foreground
Definition tilespec.c:372
struct sprite * infratile
Definition tilespec.c:355
struct anim * corner[8]
Definition tilespec.c:381
struct sprite * background
Definition tilespec.c:419
struct named_sprites::@265 path
struct sprite * frame[NUM_CURSOR_FRAMES]
Definition tilespec.c:285
struct sprite * patrol
Definition tilespec.c:314
struct sprite * spaceship[SPACESHIP_COUNT]
Definition tilespec.c:282
struct sprite * rmact
Definition tilespec.c:366
struct named_sprites::@264 city
struct named_sprites::@259 units
struct sprite * selected[EDGE_COUNT]
Definition tilespec.c:405
int num_stack_sprites
Definition tilespec.c:292
struct anim * facing[U_LAST][DIR8_MAGIC_MAX][ACTIVITY_LAST]
Definition tilespec.c:273
struct sprite * transform
Definition tilespec.c:312
struct named_sprites::@266 user
struct sprite * tile_shieldnum[NUM_TILES_DIGITS]
Definition tilespec.c:332
struct sprite ** fullfog
Definition tilespec.c:360
struct sprite_vector unworked_tile_overlay
Definition tilespec.c:340
enum extrastyle_id extrastyle
Definition tilespec.c:367
struct sprite * tile_foodnum[NUM_TILES_DIGITS]
Definition tilespec.c:331
struct sprite * turns[NUM_TILES_DIGITS]
Definition tilespec.c:347
struct sprite_vector nation_flag
Definition tilespec.c:276
struct named_sprites::@272 player[MAX_NUM_PLAYER_SLOTS]
struct sprite * nonnative
Definition tilespec.c:404
struct sprite * plant
Definition tilespec.c:307
union named_sprites::@268::@274::@276::@277 ru
bool no_more_stack_sprites
Definition tilespec.c:293
struct city_sprite * single_wall
Definition tilespec.c:336
struct sprite * indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS]
Definition tilespec.c:247
struct sprite * borders[EDGE_COUNT][2]
Definition tilespec.c:407
struct sprite * size_tens[NUM_TILES_DIGITS]
Definition tilespec.c:329
struct city_sprite * tile
Definition tilespec.c:334
struct named_sprites::@269 grid
struct sprite * disorder
Definition tilespec.c:326
struct sprite * tile_tradenum[NUM_TILES_DIGITS]
Definition tilespec.c:333
struct sprite * unworked_tile
Definition tilespec.c:264
struct named_sprites::@260 cursor[CURSOR_LAST]
struct sprite * waypoint
Definition tilespec.c:351
struct sprite * pillage
Definition tilespec.c:308
struct sprite * fortified
Definition tilespec.c:303
struct sprite * dither_tile
Definition tilespec.c:258
struct sprite * coastline[EDGE_COUNT]
Definition tilespec.c:406
union named_sprites::@268::@274 u
struct sprite * tired
Definition tilespec.c:318
struct style_citizen_set style_citizen_sets
Definition tilespec.c:280
struct sprite * treaty_thumb[2]
Definition tilespec.c:249
struct sprite * sentry
Definition tilespec.c:309
struct sprite * tax_luxury
Definition tilespec.c:257
struct sprite_vector unit
Definition tilespec.c:288
struct sprite * building[B_LAST]
Definition tilespec.c:268
struct sprite * turns_hundreds[NUM_TILES_DIGITS]
Definition tilespec.c:349
struct anim * isolated
Definition tilespec.c:378
struct sprite * unhappy[MAX_NUM_UPKEEP_SPRITES]
Definition tilespec.c:321
struct sprite_vector worked_tile_overlay
Definition tilespec.c:339
struct named_sprites::@265::@273 s[GTS_COUNT]
struct named_sprites::@267 tx
struct sprite * darkness[MAX_INDEX_CARDINAL]
Definition tilespec.c:361
struct sprite * tax_science
Definition tilespec.c:257
struct named_sprites::@263 upkeep
struct anim * select
Definition tilespec.c:294
struct sprite * specific
Definition tilespec.c:346
struct sprite * color
Definition tilespec.c:413
struct sprite * unavailable
Definition tilespec.c:403
struct sprite * worked_tile
Definition tilespec.c:263
struct river_sprites rivers
Definition tilespec.c:393
struct drawing_data * drawing[MAX_NUM_ITEMS]
Definition tilespec.c:422
struct sprite * go_to
Definition tilespec.c:305
struct citybar_sprites citybar
Definition tilespec.c:342
struct sprite * auto_explore
Definition tilespec.c:302
struct sprite * turns_tens[NUM_TILES_DIGITS]
Definition tilespec.c:348
struct sprite * tech[A_LAST]
Definition tilespec.c:267
struct sprite * nuke
Definition tilespec.c:289
struct anim * action_decision_want
Definition tilespec.c:296
struct sprite * convert
Definition tilespec.c:315
struct sprite * worked[EDGE_COUNT]
Definition tilespec.c:402
struct sprite_vector overlays
Definition tilespec.c:410
struct named_sprites::@261 explode
struct editor_sprites editor
Definition tilespec.c:343
struct sprite * size_hundreds[NUM_TILES_DIGITS]
Definition tilespec.c:330
struct sprite * activity
Definition tilespec.c:364
struct named_sprites::@268::@274::@275 bmf
struct anim * single
Definition tilespec.c:369
struct named_sprites::@268 extras[MAX_EXTRA_TYPES]
struct anim * odd[MAX_INDEX_HALF]
Definition tilespec.c:389
struct sprite * size[NUM_TILES_DIGITS]
Definition tilespec.c:328
struct sprite * fortifying
Definition tilespec.c:304
struct sprite * main[EDGE_COUNT]
Definition tilespec.c:399
struct sprite * events[E_COUNT]
Definition tilespec.c:254
struct sprite * auto_attack
Definition tilespec.c:300
struct named_sprites::@268::@274::@276 road
struct sprite * icon[ICON_COUNT]
Definition tilespec.c:252
struct named_sprites::@270 colors
struct anim * even[MAX_INDEX_HALF]
Definition tilespec.c:387
struct city_sprite * wall[NUM_WALL_TYPES]
Definition tilespec.c:337
struct anim * middleground
Definition tilespec.c:374
struct anim * background
Definition tilespec.c:375
struct sprite * connect
Definition tilespec.c:313
struct sprite * fog
Definition tilespec.c:358
struct named_sprites::@258 mask
struct sprite * arrow[ARROW_LAST]
Definition tilespec.c:250
struct sprite * grid_borders[EDGE_COUNT][2]
Definition tilespec.c:417
struct anim * cardinals[MAX_INDEX_CARDINAL]
Definition tilespec.c:370
struct named_sprites::@268::@274::@276::@277::@278 combo
struct sprite * attention
Definition tilespec.c:354
struct city_sprite * occupied
Definition tilespec.c:338
struct sprite * tile
Definition tilespec.c:261
struct sprite * cultivate
Definition tilespec.c:306
struct sprite * auto_worker
Definition tilespec.c:301
struct sprite * lowfuel
Definition tilespec.c:317
char flag_graphic_str[MAX_LEN_NAME]
Definition nation.h:103
char flag_graphic_alt[MAX_LEN_NAME]
Definition nation.h:104
enum borders_mode borders
Definition goto.c:52
struct anim * outlet[MAX_INDEX_CARDINAL]
Definition tilespec.c:226
struct anim * spec[MAX_INDEX_CARDINAL]
Definition tilespec.c:224
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
Definition map.c:40
struct citizen_set * sets
Definition tilespec.c:242
char graphic_alt2[MAX_LEN_NAME]
Definition terrain.h:82
char graphic_alt[MAX_LEN_NAME]
Definition terrain.h:81
char graphic_str[MAX_LEN_NAME]
Definition terrain.h:80
Definition tile.h:50
char * spec_sprite
Definition tile.h:67
struct unit_list * units
Definition tile.h:58
struct extra_type * placing
Definition tile.h:61
struct city * worked
Definition tile.h:59
char given_name[MAX_LEN_NAME]
Definition tilespec.c:503
int num_cardinal_tileset_dirs
Definition tilespec.c:557
int occupied_offset_x
Definition tilespec.c:550
int stack_size_offset_y
Definition tilespec.c:549
struct named_sprites sprites
Definition tilespec.c:579
int ts_topo_idx
Definition tilespec.c:517
int hex_height
Definition tilespec.c:516
enum fog_style fogstyle
Definition tilespec.c:533
int normal_tile_height
Definition tilespec.c:519
int unit_tile_width
Definition tilespec.c:521
int city_offset_y
Definition tilespec.c:539
char * main_intro_filename
Definition tilespec.c:529
enum ts_type type
Definition tilespec.c:515
int city_size_offset_x
Definition tilespec.c:540
int num_preferred_themes
Definition tilespec.c:587
char version[MAX_LEN_NAME]
Definition tilespec.c:504
int default_time_per_frame
Definition tilespec.c:527
int full_tile_height
Definition tilespec.c:520
int small_sprite_width
Definition tilespec.c:522
char ** preferred_themes
Definition tilespec.c:588
struct extra_type_list * flagged_bases_list
Definition tilespec.c:585
enum darkness_style darkness_style
Definition tilespec.c:534
int activity_offset_x
Definition tilespec.c:544
int citybar_offset_y
Definition tilespec.c:542
int normal_tile_width
Definition tilespec.c:519
float scale
Definition tilespec.c:509
int svg_height
Definition tilespec.c:525
int unit_tile_height
Definition tilespec.c:521
int hex_width
Definition tilespec.c:516
int select_offset_y
Definition tilespec.c:547
int city_flag_offset_x
Definition tilespec.c:537
int unit_flag_offset_x
Definition tilespec.c:536
int occupied_offset_y
Definition tilespec.c:551
char * description
Definition tilespec.c:508
int max_upkeep_height
Definition tilespec.c:524
int unit_flag_offset_y
Definition tilespec.c:536
int unit_upkeep_offset_y
Definition tilespec.c:552
struct estyle_hash * estyle_hash
Definition tilespec.c:575
char * for_ruleset
Definition tilespec.c:511
int activity_offset_y
Definition tilespec.c:545
int num_index_valid
Definition tilespec.c:558
int select_offset_x
Definition tilespec.c:546
int num_index_cardinal
Definition tilespec.c:558
int full_tile_width
Definition tilespec.c:520
struct small_sprite_list * small_sprites
Definition tilespec.c:567
struct extra_type_list * style_lists[ESTYLE_COUNT]
Definition tilespec.c:583
enum direction8 unit_default_orientation
Definition tilespec.c:531
struct tileset::tileset_layer layers[MAX_NUM_LAYERS]
int small_sprite_height
Definition tilespec.c:522
int city_size_offset_y
Definition tilespec.c:540
struct sprite_hash * sprite_hash
Definition tilespec.c:570
int unit_upkeep_small_offset_y
Definition tilespec.c:553
int unit_offset_x
Definition tilespec.c:538
int unit_offset_y
Definition tilespec.c:538
enum mapview_layer layer_order[LAYER_COUNT]
Definition tilespec.c:513
int city_offset_x
Definition tilespec.c:539
struct anim_hash * anim_hash
Definition tilespec.c:577
int priority
Definition tilespec.c:505
enum direction8 cardinal_tileset_dirs[8]
Definition tilespec.c:559
enum direction8 valid_tileset_dirs[8]
Definition tilespec.c:559
struct color_system * color_system
Definition tilespec.c:581
char * summary
Definition tilespec.c:507
char name[512]
Definition tilespec.c:502
int city_flag_offset_y
Definition tilespec.c:537
struct drawing_hash * tile_hash
Definition tilespec.c:573
int num_valid_tileset_dirs
Definition tilespec.c:557
int stack_size_offset_x
Definition tilespec.c:548
struct specfile_list * specfiles
Definition tilespec.c:566
int tilelabel_offset_y
Definition tilespec.c:543
struct strvec * list
Definition tilespec.c:1126
Definition unit.h:139
bool occupied
Definition unit.h:221
int battlegroup
Definition unit.h:193
enum unit_activity activity
Definition unit.h:158
int moves_left
Definition unit.h:151
struct unit::@83 orders
int hp
Definition unit.h:152
int fuel
Definition unit.h:154
bool colored
Definition unit.h:224
enum direction8 facing
Definition unit.h:143
struct tile * tile
Definition unit.h:141
struct unit::@84::@86 client
struct extra_type * activity_target
Definition unit.h:166
bool repeat
Definition unit.h:198
int color_index
Definition unit.h:225
int veteran
Definition unit.h:153
enum server_side_agent ssa_controller
Definition unit.h:174
int store_width
int store_height
struct civ_map map
int style_of_city(const struct city *pcity)
Definition style.c:196
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:742
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:851
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char ** ordered_gfx_fextensions(void)
Definition svgflag.c:53
void get_flag_dimensions(struct sprite *flag, struct area_rect *rect, int svg_height)
Definition svgflag.c:123
#define is_svg_flag_enabled()
Definition svgflag.h:30
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:157
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:90
static Tech_type_id advance_count(void)
Definition tech.h:167
#define advance_iterate(_p)
Definition tech.h:273
#define advance_iterate_end
Definition tech.h:274
#define A_LAST
Definition tech.h:45
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:139
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:585
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define T_UNKNOWN
Definition terrain.h:62
#define is_ocean_tile(ptile)
Definition terrain.h:197
#define terrain_type_iterate_end
Definition terrain.h:273
#define tile_index(_pt_)
Definition tile.h:89
#define tile_worked(_tile)
Definition tile.h:119
@ TILE_KNOWN_UNSEEN
Definition tile.h:37
@ TILE_UNKNOWN
Definition tile.h:36
@ TILE_KNOWN_SEEN
Definition tile.h:38
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
static int fill_unit_type_sprite_array(const struct tileset *t, struct drawn_sprite *sprs, const struct unit_type *putype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:4760
void advance_global_anim_state(void)
Definition tilespec.c:6794
struct sprite * get_government_sprite(const struct tileset *t, const struct government *gov)
Definition tilespec.c:7062
void tileset_load_tiles(struct tileset *t)
Definition tilespec.c:3836
struct sprite * get_nuke_explode_sprite(const struct tileset *t)
Definition tilespec.c:7208
#define sprite_hash_iterate(hash, tag_name, sprite)
Definition tilespec.c:472
int tileset_hex_width(const struct tileset *t)
Definition tilespec.c:747
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:7051
#define SET_SPRITE_DEPR_ALT(field, tag, alt, ver)
Definition tilespec.c:2976
int tileset_unit_width(const struct tileset *t)
Definition tilespec.c:823
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:5898
struct unit * get_drawable_unit(const struct tileset *t, struct tile *ptile, const struct city *citymode)
Definition tilespec.c:6805
static int check_sprite_type(const char *sprite_type, const char *tile_section)
Definition tilespec.c:1911
struct sprite * get_attention_crosshair_sprite(const struct tileset *t)
Definition tilespec.c:7269
int tileset_unit_height(const struct tileset *t)
Definition tilespec.c:831
static struct tileset * tileset_new(void)
Definition tilespec.c:997
#define MAX_INDEX_VALID
Definition tilespec.c:112
void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
Definition tilespec.c:4010
static void free_all_anims(struct tileset *t)
Definition tilespec.c:6845
static bool check_tilespec_capabilities(struct section_file *file, const char *which, const char *us_capstr, const char *filename, bool verbose)
Definition tilespec.c:1205
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:927
static struct sprite * load_gfx_file(const char *gfx_filename, bool svgflag)
Definition tilespec.c:1604
#define specfile_list_iterate_end
Definition tilespec.c:436
static struct sprite * create_plr_sprite(struct color *pcolor)
Definition tilespec.c:2886
int tileset_svg_flag_height(struct tileset *t)
Definition tilespec.c:7854
#define SPEC_CAPSTR
Definition tilespec.c:98
static struct sprite * get_unit_nation_flag_sprite(const struct tileset *t, const struct unit *punit)
Definition tilespec.c:4679
direction4
Definition tilespec.c:139
@ DIR4_EAST
Definition tilespec.c:140
@ DIR4_NORTH
Definition tilespec.c:140
@ DIR4_SOUTH
Definition tilespec.c:140
@ DIR4_WEST
Definition tilespec.c:140
struct tileset * get_tileset(void)
Definition tilespec.c:718
#define MAX_NUM_MATCH_WITH
Definition tilespec.c:188
void tileset_setup_government(struct tileset *t, struct government *gov)
Definition tilespec.c:4620
#define sprite_hash_iterate_end
Definition tilespec.c:475
struct sprite * get_city_flag_sprite(const struct tileset *t, const struct city *pcity)
Definition tilespec.c:4670
void tileset_setup_specialist_type_default_set(struct tileset *t, Specialist_type_id id)
Definition tilespec.c:3097
static bool is_valid_tileset_dir(const struct tileset *t, enum direction8 dir)
Definition tilespec.c:1056
struct sprite * get_basic_fog_sprite(const struct tileset *t)
Definition tilespec.c:7332
static enum direction8 dir_by_tileset_name(const char *str)
Definition tilespec.c:1038
#define ADD_SPRITE_SIMPLE(s)
Definition tilespec.c:4705
static int fill_basic_road_sprite_array(const struct tileset *t, struct drawn_sprite *sprs, const struct extra_type *pextra)
Definition tilespec.c:7518
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:4779
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:815
bool tilespec_try_read(const char *tileset_name, bool verbose, int topo_id, bool global_default)
Definition tilespec.c:1360
static bool tileset_setup_unit_type_from_tag(struct tileset *t, int uidx, const char *tag)
Definition tilespec.c:3955
struct tileset * unscaled_tileset
Definition tilespec.c:592
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:5252
int fill_basic_extra_sprite_array(const struct tileset *t, struct drawn_sprite *sprs, const struct extra_type *pextra)
Definition tilespec.c:7483
#define specfile_list_iterate(list, pitem)
Definition tilespec.c:434
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:7314
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:973
void tileset_setup_tile_type(struct tileset *t, const struct terrain *pterrain)
Definition tilespec.c:4354
static const char direction4letters[4]
Definition tilespec.c:142
void tileset_player_init(struct tileset *t, struct player *pplayer)
Definition tilespec.c:7655
const struct strvec * get_tileset_list(const struct option *poption)
Definition tilespec.c:1150
int tileset_unit_layout_offset_y(const struct tileset *t)
Definition tilespec.c:908
int tileset_citybar_offset_y(const struct tileset *t)
Definition tilespec.c:936
#define MAX_NUM_UPKEEP_SPRITES
Definition tilespec.c:116
static void anim_free(struct anim *a)
Definition tilespec.c:2801
struct sprite * get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
Definition tilespec.c:7188
bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
Definition tilespec.c:5731
#define MAX_INDEX_HALF
Definition tilespec.c:111
double get_focus_unit_toggle_timeout(const struct tileset *t)
Definition tilespec.c:6748
#define SET_SPRITE_ALT_OPT(field, tag, alt)
Definition tilespec.c:2997
static int calculate_max_upkeep_height(const struct tileset *t)
Definition tilespec.c:839
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:5415
#define TILE_SECTION_PREFIX
Definition tilespec.c:107
static struct city_sprite * load_city_sprite(struct tileset *t, const char *tag)
Definition tilespec.c:3320
static char * valid_index_str(const struct tileset *t, int idx)
Definition tilespec.c:2760
void tileset_free_tiles(struct tileset *t)
Definition tilespec.c:6858
#define ADD_ANIM_FULL(s)
Definition tilespec.c:4713
void tileset_setup_impr_type(struct tileset *t, struct impr_type *pimprove)
Definition tilespec.c:4044
static struct tileset * tileset_read_toplevel(const char *tileset_name, bool verbose, int topology_id, float scale)
Definition tilespec.c:1932
static bool sprite_exists(const struct tileset *t, const char *tag_name)
Definition tilespec.c:2926
const struct sprite_vector * get_unit_explode_animation(const struct tileset *t)
Definition tilespec.c:7197
#define TILESPEC_CAPSTR
Definition tilespec.c:82
struct sprite * load_popup_sprite(const char *tag)
Definition tilespec.c:7862
static void unload_all_sprites(struct tileset *t)
Definition tilespec.c:6831
static const char * dir_get_tileset_name(enum direction8 dir)
Definition tilespec.c:1011
#define SET_SPRITE_UNSCALED(field, tag)
Definition tilespec.c:2952
void tileset_background_init(struct tileset *t)
Definition tilespec.c:7735
void tileset_setup_tech_type(struct tileset *t, struct advance *padvance)
Definition tilespec.c:4060
static const int DIR4_TO_DIR8[4]
Definition tilespec.c:146
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:5686
static void unload_sprite(struct tileset *t, const char *tag_name)
Definition tilespec.c:2902
static void drawing_data_destroy(struct drawing_data *draw)
Definition tilespec.c:686
static int fill_terrain_sprite_darkness(struct tileset *t, struct drawn_sprite *sprs, const struct tile *ptile, struct terrain **tterrain_near)
Definition tilespec.c:5622
#define small_sprite_list_iterate_end
Definition tilespec.c:465
static struct drawing_data * drawing_data_new(void)
Definition tilespec.c:674
static struct anim * get_city_anim(const struct city_sprite *city_sprite, const struct city *pcity)
Definition tilespec.c:3243
static void build_tile_data(const struct tile *ptile, struct terrain *pterrain, struct terrain **tterrain_near, bv_extras *textras_near)
Definition tilespec.c:4728
static void tileset_player_free(struct tileset *t, int plrid)
Definition tilespec.c:7706
float tileset_scale(const struct tileset *t)
Definition tilespec.c:953
#define UNKNOWN(dir)
int tileset_unit_with_small_upkeep_height(const struct tileset *t)
Definition tilespec.c:897
bool tileset_layer_in_category(enum mapview_layer layer, enum layer_category cat)
Definition tilespec.c:7612
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:5748
match_style
Definition tilespec.c:149
@ MATCH_SAME
Definition tilespec.c:151
@ MATCH_FULL
Definition tilespec.c:153
@ MATCH_PAIR
Definition tilespec.c:152
@ MATCH_NONE
Definition tilespec.c:150
#define small_sprite_list_iterate(list, pitem)
Definition tilespec.c:463
static void ts_cb(const char *modpack_name, const char *filename, void *data)
Definition tilespec.c:1332
int tileset_num_city_colors(const struct tileset *t)
Definition tilespec.c:981
int index_ts_topology(int idx)
Definition tilespec.c:1111
#define NUM_TILES_HP_BAR
Definition tilespec.c:114
#define anim_hash_iterate(hash, tag_name, sprite)
Definition tilespec.c:482
#define TILESPEC_SUFFIX
Definition tilespec.c:106
bool tileset_is_isometric(const struct tileset *t)
Definition tilespec.c:738
bool tileset_use_hard_coded_fog(const struct tileset *t)
Definition tilespec.c:989
void tileset_use_preferred_theme(const struct tileset *t)
Definition tilespec.c:7348
#define FULL_TILE_X_OFFSET
Definition tilespec.c:4691
sprite_type
Definition tilespec.c:156
@ CELL_CORNER
Definition tilespec.c:158
@ CELL_WHOLE
Definition tilespec.c:157
static int global_anim_time
Definition tilespec.c:598
void tileset_setup_city_tiles(struct tileset *t, int style)
Definition tilespec.c:6683
struct sprite * get_nation_shield_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:7032
const char * tileset_description(struct tileset *t)
Definition tilespec.c:7830
#define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name)
#define SET_ANIM_OPT(field, tag)
Definition tilespec.c:3014
void tileset_background_free(struct tileset *t)
Definition tilespec.c:7754
#define MAX_NUM_LAYERS
Definition tilespec.c:182
int tileset_unit_layout_small_offset_y(const struct tileset *t)
Definition tilespec.c:917
struct sprite * get_event_sprite(const struct tileset *t, enum event_type event)
Definition tilespec.c:7179
void toggle_focus_unit_state(struct tileset *t)
Definition tilespec.c:6782
#define ADD_FRAME0_IF_NOT_NULL(x)
void tilespec_reread_frozen_refresh(const char *tname)
Definition tilespec.c:1592
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:963
void tileset_free(struct tileset *t)
Definition tilespec.c:1315
static const char * cardinal_index_str(const struct tileset *t, int idx)
Definition tilespec.c:2740
#define NUM_TILES_DIGITS
Definition tilespec.c:115
void focus_unit_in_combat(struct tileset *t)
Definition tilespec.c:6773
static int tileset_upkeep_height(const struct tileset *t)
Definition tilespec.c:876
const char * tileset_summary(struct tileset *t)
Definition tilespec.c:7822
struct sprite * get_icon_sprite(const struct tileset *t, enum icon_type icon)
Definition tilespec.c:7258
static void ensure_big_sprite(struct specfile *sf, const char *tset_name)
Definition tilespec.c:1640
#define ADD_ANIM_SPRITE(s, draw_fog, x_offset, y_offset)
Definition tilespec.c:4709
static bool tileset_update
Definition tilespec.c:596
#define FULL_TILE_Y_OFFSET
Definition tilespec.c:4692
struct sprite * get_indicator_sprite(const struct tileset *t, enum indicator_type indicator, int idx)
Definition tilespec.c:7278
struct sprite * get_sample_city_sprite(const struct tileset *t, int style_idx)
Definition tilespec.c:7129
#define ADD_SPRITE_FULL(s)
Definition tilespec.c:4706
void tileset_setup_extra(struct tileset *t, struct extra_type *pextra)
Definition tilespec.c:4080
static void anim_advance_time(struct anim *a)
Definition tilespec.c:3066
void tileset_init(struct tileset *t)
Definition tilespec.c:7409
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:5294
static char * tilespec_gfx_filename(const char *gfx_filename, const char *tset_name)
Definition tilespec.c:1846
const char * tileset_basename(const struct tileset *t)
Definition tilespec.c:730
int fill_basic_terrain_layer_sprite_array(struct tileset *t, struct drawn_sprite *sprs, int layer, struct terrain *pterrain)
Definition tilespec.c:7450
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:791
#define LOAD_FACING_SPRITE(dir)
#define SET_SPRITE_NOTSMOOTH(field, tag)
Definition tilespec.c:2943
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:4969
static bool is_extra_drawing_enabled(struct extra_type *pextra)
Definition tilespec.c:5966
struct sprite * get_spaceship_sprite(const struct tileset *t, enum spaceship_part part)
Definition tilespec.c:6956
int tileset_unit_with_upkeep_height(const struct tileset *t)
Definition tilespec.c:885
static void tileset_free_toplevel(struct tileset *t)
Definition tilespec.c:1243
static struct sprite * load_sprite(struct tileset *t, const char *tag_name, bool scale, bool smooth, bool svgflag)
Definition tilespec.c:2816
struct sprite * get_cursor_sprite(const struct tileset *t, enum cursor_type cursor, int *hot_x, int *hot_y, int frame)
Definition tilespec.c:7239
static const char edge_name[EDGE_COUNT][3]
Definition tilespec.c:144
struct color_system * get_color_system(const struct tileset *t)
Definition tilespec.c:7340
int tileset_hex_height(const struct tileset *t)
Definition tilespec.c:756
void reset_focus_unit_state(struct tileset *t)
Definition tilespec.c:6761
static const char * citizen_rule_name(enum citizen_category citizen)
Definition tilespec.c:2714
static void tileset_setup_citizen_types_default_set(struct tileset *t)
Definition tilespec.c:3192
bool tileset_is_fully_loaded(void)
Definition tilespec.c:7798
static struct sprite * anim_get_current_frame(struct anim *a)
Definition tilespec.c:3077
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:5375
#define ADD_ANIM_SPRITE_SIMPLE(s)
Definition tilespec.c:4711
const struct citybar_sprites * get_citybar_sprites(const struct tileset *t)
Definition tilespec.c:7216
static bool is_cardinal_tileset_dir(const struct tileset *t, enum direction8 dir)
Definition tilespec.c:1074
void unload_popup_sprite(const char *tag)
Definition tilespec.c:7870
#define SET_SPRITE(field, tag)
Definition tilespec.c:2933
static void tileset_lookup_sprite_tags(struct tileset *t)
Definition tilespec.c:3368
struct sprite * get_arrow_sprite(const struct tileset *t, enum arrow_type arrow)
Definition tilespec.c:7146
struct sprite * get_unit_unhappy_sprite(const struct tileset *t, const struct unit *punit, int happy_cost)
Definition tilespec.c:7295
#define NUM_CORNER_DIRS
Definition tilespec.c:555
static int fill_basic_base_sprite_array(const struct tileset *t, struct drawn_sprite *sprs, const struct extra_type *pextra)
Definition tilespec.c:7566
static void tileset_setup_base(struct tileset *t, const struct extra_type *pextra, const char *tag)
Definition tilespec.c:4319
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:5020
void finish_loading_sprites(struct tileset *t)
Definition tilespec.c:3820
static bool tileset_scan_single_list(struct tileset *t, const char *spec_filenames[], int num_spec_files, bool verbose, bool duplicates_ok)
Definition tilespec.c:1877
#define anim_hash_iterate_end
Definition tilespec.c:485
static struct anim * anim_new(int frames, int time_per_frame)
Definition tilespec.c:2783
struct sprite * tiles_lookup_sprite_tag_alt(struct tileset *t, enum log_level level, const char *tag, const char *alt, const char *alt2, const char *what, const char *name, bool scale)
Definition tilespec.c:3847
#define SET_EDITOR_SPRITE(x)
#define SET_SPRITE_ALT(field, tag, alt)
Definition tilespec.c:2962
#define SET_SPRITE_OPT(field, tag)
Definition tilespec.c:2994
void tilespec_reread_callback(struct option *poption)
Definition tilespec.c:1555
static void tileset_setup_specialist_type(struct tileset *t, struct citizen_set *set, Specialist_type_id id, const char *tag_group, const char *set_name, bool required)
Definition tilespec.c:3107
static bool load_river_sprites(struct tileset *t, struct river_sprites *store, const char *tag_pfx)
Definition tilespec.c:3786
const char * tileset_name_get(struct tileset *t)
Definition tilespec.c:7806
static char * tilespec_fullname(const char *tileset_name)
Definition tilespec.c:1181
static const struct citizen_graphic * get_citizen_graphic(const struct citizen_set *set, enum citizen_category type)
Definition tilespec.c:6966
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:6033
#define ADD_SPRITE(s, draw_fog, x_offset, y_offset)
Definition tilespec.c:4703
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:802
static struct anim * anim_load(struct tileset *t, const char *tag, int time_per_frame)
Definition tilespec.c:3025
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:7157
static bool tileset_setup_unit_direction(struct tileset *t, int uidx, const char *base_str, enum direction8 dir, enum unit_activity activity, bool has_icon)
Definition tilespec.c:3893
struct sprite * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Definition tilespec.c:6989
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:5469
const char * tileset_version(struct tileset *t)
Definition tilespec.c:7814
static bool focus_unit_state
Definition tilespec.c:594
static void free_city_sprite(struct city_sprite *city_sprite)
Definition tilespec.c:3348
static int ts_topology_index(int actual_topology)
Definition tilespec.c:1089
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7075
char * tileset_what_ruleset(struct tileset *t)
Definition tilespec.c:7838
static void ts_list_cb(const char *modpack_name, const char *filename, void *data)
Definition tilespec.c:1133
struct sprite * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:7023
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:779
int tileset_tilelabel_offset_y(const struct tileset *t)
Definition tilespec.c:945
static void tileset_setup_citizen_types(struct tileset *t, struct citizen_set *set, const char *tag_group, const char *set_name, bool required)
Definition tilespec.c:3201
static void tileset_setup_road(struct tileset *t, struct extra_type *pextra, const char *tag)
Definition tilespec.c:4210
struct sprite * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Definition tilespec.c:7041
#define MATCH(dir)
static int get_irrigation_index(const struct tileset *t, struct extra_type *pextra, bv_extras *textras_near)
Definition tilespec.c:5232
#define ADD_FRAME0_SIMPLE(s)
Definition tilespec.c:4717
#define MAX_INDEX_CARDINAL
Definition tilespec.c:110
#define ADD_SPRITE_SIZE(s, draw_fog, x_offset, y_offset, w_in, h_in)
Definition tilespec.c:4694
static int load_city_thresholds_anims(struct tileset *t, const char *tag, char *graphic, char *graphic_alt, struct city_style_threshold **thresholds)
Definition tilespec.c:3279
void tileset_error(enum log_level level, const char *tset_name, const char *format,...)
Definition tilespec.c:650
const struct editor_sprites * get_editor_sprites(const struct tileset *t)
Definition tilespec.c:7228
int tileset_topo_index(struct tileset *t)
Definition tilespec.c:7846
bool tilespec_reread(const char *new_tileset_name, bool game_fully_initialized, float scale)
Definition tilespec.c:1401
spec_file_types
Definition tilespec.c:161
@ SFILE_COMMON
Definition tilespec.c:162
@ SFILE_PIXEL
Definition tilespec.c:164
@ SFILE_LAST
Definition tilespec.c:165
@ SFILE_SVG
Definition tilespec.c:163
void tileset_setup_nation_flag(struct tileset *t, struct nation_type *nation)
Definition tilespec.c:4635
void tileset_ruleset_reset(struct tileset *t)
Definition tilespec.c:7770
#define SET_ANIM(field, tag)
Definition tilespec.c:3004
static void scan_specfile(struct tileset *t, struct specfile *sf, bool duplicates_ok)
Definition tilespec.c:1681
enum mapview_layer tileset_get_layer(const struct tileset *t, int n)
Definition tilespec.c:7602
#define NUM_EDGE_TILES
Definition tilespec.h:101
#define NUM_CURSOR_FRAMES
Definition tilespec.h:306
indicator_type
Definition tilespec.h:308
@ INDICATOR_COUNT
Definition tilespec.h:312
arrow_type
Definition tilespec.h:202
@ ARROW_LAST
Definition tilespec.h:206
@ ARROW_MINUS
Definition tilespec.h:205
@ ARROW_RIGHT
Definition tilespec.h:203
@ ARROW_PLUS
Definition tilespec.h:204
#define TS_TOPO_ISOHEX
Definition tilespec.h:458
#define TERRAIN_LAYER_COUNT
Definition tilespec.h:176
#define sprite_vector_iterate_end
Definition tilespec.h:46
#define NUM_CORNER_TILES
Definition tilespec.h:108
#define NUM_TILES_PROGRESS
Definition tilespec.h:198
#define MAX_NUM_CITIZEN_SPRITES
Definition tilespec.h:200
#define TS_TOPO_HEX
Definition tilespec.h:457
#define TS_TOPO_SQUARE
Definition tilespec.h:456
layer_category
Definition tilespec.h:192
@ LAYER_CATEGORY_TILE
Definition tilespec.h:194
@ LAYER_CATEGORY_CITY
Definition tilespec.h:193
@ LAYER_CATEGORY_UNIT
Definition tilespec.h:195
icon_type
Definition tilespec.h:315
@ ICON_COUNT
Definition tilespec.h:318
@ EDGE_UD
Definition tilespec.h:95
@ EDGE_LR
Definition tilespec.h:96
@ EDGE_COUNT
Definition tilespec.h:97
spaceship_part
Definition tilespec.h:321
@ SPACESHIP_COUNT
Definition tilespec.h:329
#define NUM_WALL_TYPES
Definition tilespec.h:362
#define sprite_vector_iterate(sprite_vec, psprite)
Definition tilespec.h:44
cursor_type
Definition tilespec.h:290
@ CURSOR_LAST
Definition tilespec.h:302
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2723
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2512
bool is_flagless_to_player(const struct unit *punit, const struct player *pplayer)
Definition unit.c:382
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
#define unit_tile(_pu)
Definition unit.h:408
#define BATTLEGROUP_NONE
Definition unit.h:192
#define unit_owner(_pu)
Definition unit.h:407
#define activity_type_iterate(_act_)
Definition unit.h:287
#define activity_type_iterate_end
Definition unit.h:292
#define MAX_NUM_BATTLEGROUPS
Definition unit.h:191
#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:126
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1604
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:93
#define utype_fuel(ptype)
Definition unittype.h:849
#define unit_type_iterate(_p)
Definition unittype.h:865
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:872
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35