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 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 /* utility */
19 #include "support.h"
20
21 /* common */
22 #include "disaster.h"
23 #include "game.h"
24 #include "government.h"
25 #include "improvement.h"
26 #include "requirements.h"
27 #include "specialist.h"
28 #include "style.h"
29 #include "tech.h"
30
31 #include "validity.h"
32
33 /**************************************************************************
34 Check if universal is mentioned in the requirement vector.
35 **************************************************************************/
universal_in_req_vec(const struct universal * uni,const struct requirement_vector * preqs)36 static bool universal_in_req_vec(const struct universal *uni,
37 const struct requirement_vector *preqs)
38 {
39 requirement_vector_iterate(preqs, preq) {
40 if (are_universals_equal(uni, &preq->source)) {
41 return TRUE;
42 }
43 } requirement_vector_iterate_end;
44
45 return FALSE;
46 }
47
48 struct effect_list_cb_data
49 {
50 bool needed;
51 struct universal *uni;
52 requirers_cb cb;
53 };
54
55 /**************************************************************************
56 Callback to check if effect needs universal.
57 **************************************************************************/
effect_list_universal_needed_cb(const struct effect * peffect,void * data)58 static bool effect_list_universal_needed_cb(const struct effect *peffect,
59 void *data)
60 {
61 struct effect_list_cb_data *cbdata = (struct effect_list_cb_data *)data;
62
63 if (universal_in_req_vec(cbdata->uni, &peffect->reqs)) {
64 cbdata->cb(R__("Effect"));
65 cbdata->needed = TRUE;
66 }
67
68 /* Always continue to next until all effects checked */
69 return TRUE;
70 }
71
72 /**************************************************************************
73 Check if anything in ruleset needs universal
74 **************************************************************************/
is_universal_needed(struct universal * uni,requirers_cb cb)75 static bool is_universal_needed(struct universal *uni, requirers_cb cb)
76 {
77 bool needed = FALSE;
78 bool needed_by_music_style = FALSE;
79 int i;
80 struct effect_list_cb_data cb_data;
81
82 disaster_type_iterate(pdis) {
83 if (universal_in_req_vec(uni, &pdis->reqs)) {
84 cb(disaster_rule_name(pdis));
85 needed = TRUE;
86 }
87 } disaster_type_iterate_end;
88
89 improvement_iterate(pimprove) {
90 if (universal_in_req_vec(uni, &pimprove->reqs)
91 || universal_in_req_vec(uni, &pimprove->obsolete_by)) {
92 cb(improvement_rule_name(pimprove));
93 needed = TRUE;
94 }
95 } improvement_iterate_end;
96
97 governments_iterate(pgov) {
98 if (universal_in_req_vec(uni, &pgov->reqs)) {
99 cb(government_rule_name(pgov));
100 needed = TRUE;
101 }
102 } governments_iterate_end;
103
104 specialist_type_iterate(sp) {
105 struct specialist *psp = specialist_by_number(sp);
106
107 if (universal_in_req_vec(uni, &psp->reqs)) {
108 cb(specialist_rule_name(psp));
109 needed = TRUE;
110 }
111 } specialist_type_iterate_end;
112
113 extra_type_iterate(pextra) {
114 if (universal_in_req_vec(uni, &pextra->reqs)
115 || universal_in_req_vec(uni, &pextra->rmreqs)) {
116 cb(extra_rule_name(pextra));
117 needed = TRUE;
118 }
119 } extra_type_iterate_end;
120
121 action_iterate(act) {
122 action_enabler_list_iterate(action_enablers_for_action(act), enabler) {
123 if (universal_in_req_vec(uni, &(enabler->actor_reqs))
124 || universal_in_req_vec(uni, &(enabler->target_reqs))) {
125 cb(R__("Action Enabler"));
126 needed = TRUE;
127 }
128 } action_enabler_list_iterate_end;
129 } action_iterate_end;
130
131 for (i = 0; i < game.control.styles_count; i++) {
132 if (universal_in_req_vec(uni, &city_styles[i].reqs)) {
133 cb(city_style_rule_name(i));
134 needed = TRUE;
135 }
136 }
137
138 music_styles_iterate(pmus) {
139 if (universal_in_req_vec(uni, &pmus->reqs)) {
140 needed_by_music_style = TRUE;
141 }
142 } music_styles_iterate_end;
143
144 if (needed_by_music_style) {
145 cb(R__("Music Style"));
146 needed = TRUE;
147 }
148
149 cb_data.needed = FALSE;
150 cb_data.uni = uni;
151 cb_data.cb = cb;
152
153 iterate_effect_cache(effect_list_universal_needed_cb, &cb_data);
154 needed |= cb_data.needed;
155
156 return needed;
157 }
158
159 /**************************************************************************
160 Check if anything in ruleset needs tech
161 **************************************************************************/
is_tech_needed(struct advance * padv,requirers_cb cb)162 bool is_tech_needed(struct advance *padv, requirers_cb cb)
163 {
164 struct universal uni = { .value.advance = padv, .kind = VUT_ADVANCE };
165 bool needed = FALSE;
166
167 advance_iterate(A_FIRST, pdependant) {
168 if (pdependant->require[AR_ONE] == padv
169 || pdependant->require[AR_TWO] == padv
170 || pdependant->require[AR_ROOT] == padv) {
171 cb(advance_rule_name(pdependant));
172 needed = TRUE;
173 }
174 } advance_iterate_end;
175
176 unit_type_iterate(ptype) {
177 if (ptype->require_advance == padv) {
178 cb(utype_rule_name(ptype));
179 needed = TRUE;
180 }
181 } unit_type_iterate_end;
182
183 needed |= is_universal_needed(&uni, cb);
184
185 return needed;
186 }
187
188 /**************************************************************************
189 Check if anything in ruleset needs building
190 **************************************************************************/
is_building_needed(struct impr_type * pimpr,requirers_cb cb)191 bool is_building_needed(struct impr_type *pimpr, requirers_cb cb)
192 {
193 struct universal uni = { .value.building = pimpr, .kind = VUT_IMPROVEMENT };
194 bool needed = FALSE;
195
196 needed |= is_universal_needed(&uni, cb);
197
198 return needed;
199 }
200
201 /**************************************************************************
202 Check if anything in ruleset needs unit type
203 **************************************************************************/
is_utype_needed(struct unit_type * ptype,requirers_cb cb)204 bool is_utype_needed(struct unit_type *ptype, requirers_cb cb)
205 {
206 struct universal uni = { .value.utype = ptype, .kind = VUT_UTYPE };
207 bool needed = FALSE;
208
209 needed |= is_universal_needed(&uni, cb);
210
211 terrain_type_iterate(pterr) {
212 if (pterr->animal == ptype) {
213 cb(terrain_rule_name(pterr));
214 needed = TRUE;
215 }
216 } terrain_type_iterate_end;
217
218 return needed;
219 }
220