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