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 #ifndef FC__TECH_H
14 #define FC__TECH_H
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif /* __cplusplus */
19 
20 /* utility */
21 #include "bitvector.h"
22 #include "shared.h"
23 
24 /* common */
25 #include "fc_types.h"
26 #include "name_translation.h"
27 
28 struct strvec;          /* Actually defined in "utility/string_vector.h". */
29 
30 /*
31   [kept for amusement and posterity]
32 typedef int Tech_type_id;
33   Above typedef replaces old "enum tech_type_id"; see comments about
34   Unit_type_id in unit.h, since mainly apply here too, except don't
35   use Tech_type_id very widely, and don't use (-1) flag values. (?)
36 */
37 /* [more accurately]
38  * Unlike most other indices, the Tech_type_id is widely used, because it
39  * so frequently passed to packet and scripting.  The client menu routines
40  * sometimes add and substract these numbers.
41  */
42 #define A_NONE 0
43 #define A_FIRST 1
44 #define A_LAST MAX_NUM_ITEMS /* Used in the network protocol. */
45 #define A_FUTURE (A_LAST + 1)
46 #define A_ARRAY_SIZE (A_FUTURE + 1)
47 #define A_UNSET (A_LAST + 2)
48 #define A_UNKNOWN (A_LAST + 3)
49 
50 #define A_NEVER (NULL)
51 
52 /*
53    A_NONE is the root tech. All players always know this tech. It is
54    used as a flag in various cases where there is no tech-requirement.
55 
56    A_FIRST is the first real tech id value
57 
58    A_UNSET indicates that no tech is selected (for research).
59 
60    A_FUTURE indicates that the player is researching a future tech.
61 
62    A_UNKNOWN may be passed to other players instead of the actual value.
63 
64    A_LAST is a value that is guaranteed to be larger than all
65    actual Tech_type_id values.  It is used as a flag value; it can
66    also be used for fixed allocations to ensure ability to hold the
67    full number of techs.
68 
69    A_NEVER is the pointer equivalent replacement for A_LAST flag value.
70 */
71 
72 /* Changing these breaks network compatibility. */
73 /* If a new flag is added techtools.c:research_tech_lost() should be checked */
74 #define SPECENUM_NAME tech_flag_id
75 /* player gets extra tech if rearched first */
76 #define SPECENUM_VALUE0 TF_BONUS_TECH
77 /* TRANS: this and following strings are 'tech flags', which may rarely
78  * be presented to the player in ruleset help text */
79 #define SPECENUM_VALUE0NAME N_("Bonus_Tech")
80 /* "Settler" unit types can build bridges over rivers */
81 #define SPECENUM_VALUE1 TF_BRIDGE
82 #define SPECENUM_VALUE1NAME N_("Bridge")
83 /* Player can build air units */
84 #define SPECENUM_VALUE2 TF_BUILD_AIRBORNE
85 #define SPECENUM_VALUE2NAME N_("Build_Airborne")
86 /* Player can claim ocean tiles non-adjacent to border source */
87 #define SPECENUM_VALUE3 TF_CLAIM_OCEAN
88 #define SPECENUM_VALUE3NAME N_("Claim_Ocean")
89 /* Player can claim ocean tiles non-adjacent to border source as long
90  * as source is ocean tile */
91 #define SPECENUM_VALUE4 TF_CLAIM_OCEAN_LIMITED
92 #define SPECENUM_VALUE4NAME N_("Claim_Ocean_Limited")
93 #define SPECENUM_VALUE5 TECH_USER_1
94 #define SPECENUM_VALUE6 TECH_USER_2
95 #define SPECENUM_VALUE7 TECH_USER_3
96 #define SPECENUM_VALUE8 TECH_USER_4
97 #define SPECENUM_VALUE9 TECH_USER_5
98 #define SPECENUM_VALUE10 TECH_USER_6
99 #define SPECENUM_VALUE11 TECH_USER_7
100 #define SPECENUM_VALUE12 TECH_USER_LAST
101 /* Keep this last. */
102 #define SPECENUM_COUNT TF_COUNT
103 #define SPECENUM_BITVECTOR bv_tech_flags
104 #define SPECENUM_NAMEOVERRIDE
105 #include "specenum_gen.h"
106 
107 #define MAX_NUM_USER_TECH_FLAGS (TECH_USER_LAST - TECH_USER_1 + 1)
108 
109 enum tech_req {
110   AR_ONE = 0,
111   AR_TWO = 1,
112   AR_ROOT = 2,
113   AR_SIZE
114 };
115 
116 struct advance {
117   Tech_type_id item_number;
118   struct name_translation name;
119   char graphic_str[MAX_LEN_NAME];	/* which named sprite to use */
120   char graphic_alt[MAX_LEN_NAME];	/* alternate icon name */
121 
122   struct advance *require[AR_SIZE];
123   bool inherited_root_req;
124   bv_tech_flags flags;
125   struct strvec *helptext;
126 
127   /*
128    * Message displayed to the first player to get a bonus tech
129    */
130   char *bonus_message;
131 
132   /* Cost of advance in bulbs. It may be specified in ruleset, or
133    * calculated in techs_precalc_data(). However, this value wouldn't
134    * be right if game.info.tech_cost_style is TECH_COST_CIV1CIV2. */
135   double cost;
136 
137   /*
138    * Number of requirements this technology has _including_
139    * itself. Precalculated at server then send to client.
140    */
141   int num_reqs;
142 };
143 
144 BV_DEFINE(bv_techs, A_LAST);
145 
146 /* General advance/technology accessor functions. */
147 Tech_type_id advance_count(void);
148 Tech_type_id advance_index(const struct advance *padvance);
149 Tech_type_id advance_number(const struct advance *padvance);
150 
151 struct advance *advance_by_number(const Tech_type_id atype);
152 
153 struct advance *valid_advance(struct advance *padvance);
154 struct advance *valid_advance_by_number(const Tech_type_id atype);
155 
156 struct advance *advance_by_rule_name(const char *name);
157 struct advance *advance_by_translated_name(const char *name);
158 
159 const char *advance_rule_name(const struct advance *padvance);
160 const char *advance_name_translation(const struct advance *padvance);
161 
162 void user_tech_flags_init(void);
163 void user_tech_flags_free(void);
164 void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt);
165 const char *tech_flag_helptxt(enum tech_flag_id id);
166 
167 /* General advance/technology flag accessor routines */
168 bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag);
169 
170 /* Ancillary routines */
171 Tech_type_id advance_required(const Tech_type_id tech,
172 			      enum tech_req require);
173 struct advance *advance_requires(const struct advance *padvance,
174 				 enum tech_req require);
175 
176 bool techs_have_fixed_costs(void);
177 
178 bool is_future_tech(Tech_type_id tech);
179 
180 /* Initialization */
181 void techs_init(void);
182 void techs_free(void);
183 
184 void techs_precalc_data(void);
185 
186 /* Iteration */
187 
188 /* This iterates over almost all technologies.  It includes non-existent
189  * technologies, but not A_FUTURE. */
190 #define advance_index_iterate(_start, _index)				\
191 {									\
192   Tech_type_id _index = (_start);					\
193   Tech_type_id _aco_##_index = advance_count();                         \
194   for (; _index < _aco_##_index; _index++) {
195 
196 #define advance_index_iterate_end					\
197   }									\
198 }
199 
200 const struct advance *advance_array_last(void);
201 
202 #define advance_iterate(_start, _p)					\
203 {									\
204   struct advance *_p = advance_by_number(_start);			\
205   if (NULL != _p) {							\
206     for (; _p <= advance_array_last(); _p++) {
207 
208 #define advance_iterate_end						\
209     }									\
210   }									\
211 }
212 
213 #define advance_active_iterate(_p)                                      \
214   advance_iterate(A_FIRST, _p) {                                         \
215     if (_p->require[AR_ONE] != A_NEVER) {
216 
217 #define advance_active_iterate_end                                      \
218     }                                                                   \
219   } advance_iterate_end;
220 
221 
222 /* Advance requirements iterator.
223  * Iterates over 'goal' and all its requirements (including root_reqs),
224  * recursively. */
225 struct advance_req_iter;
226 
227 size_t advance_req_iter_sizeof(void);
228 struct iterator *advance_req_iter_init(struct advance_req_iter *it,
229                                        const struct advance *goal);
230 
231 #define advance_req_iterate(_goal, _padvance)                               \
232   generic_iterate(struct advance_req_iter, const struct advance *,          \
233                   _padvance, advance_req_iter_sizeof, advance_req_iter_init,\
234                   _goal)
235 #define advance_req_iterate_end generic_iterate_end
236 
237 /* Iterates over all the root requirements of 'goal'.
238  * (Not including 'goal' itself, unless it is the special case of a
239  * self-root-req technology.) */
240 struct advance_root_req_iter;
241 
242 size_t advance_root_req_iter_sizeof(void);
243 struct iterator *advance_root_req_iter_init(struct advance_root_req_iter *it,
244                                             const struct advance *goal);
245 
246 #define advance_root_req_iterate(_goal, _padvance)                          \
247   generic_iterate(struct advance_root_req_iter, const struct advance *,     \
248                   _padvance, advance_root_req_iter_sizeof,                  \
249                   advance_root_req_iter_init,                               \
250                   _goal)
251 #define advance_root_req_iterate_end generic_iterate_end
252 
253 #ifdef __cplusplus
254 }
255 #endif /* __cplusplus */
256 
257 #endif  /* FC__TECH_H */
258