1 /****************************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Team
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 /* common */
19 #include "extras.h"
20 #include "game.h"
21 #include "map.h"
22 #include "tile.h"
23 #include "unit.h"
24
25 #include "base.h"
26
27 /****************************************************************************
28 Check if base provides effect
29 ****************************************************************************/
base_has_flag(const struct base_type * pbase,enum base_flag_id flag)30 bool base_has_flag(const struct base_type *pbase, enum base_flag_id flag)
31 {
32 return BV_ISSET(pbase->flags, flag);
33 }
34
35 /****************************************************************************
36 Returns TRUE iff any cardinally adjacent tile contains a base with
37 the given flag (does not check ptile itself)
38 ****************************************************************************/
is_base_flag_card_near(const struct tile * ptile,enum base_flag_id flag)39 bool is_base_flag_card_near(const struct tile *ptile, enum base_flag_id flag)
40 {
41 extra_type_by_cause_iterate(EC_BASE, pextra) {
42 if (base_has_flag(extra_base_get(pextra), flag)) {
43 cardinal_adjc_iterate(ptile, adjc_tile) {
44 if (tile_has_extra(adjc_tile, pextra)) {
45 return TRUE;
46 }
47 } cardinal_adjc_iterate_end;
48 }
49 } extra_type_by_cause_iterate_end;
50
51 return FALSE;
52 }
53
54 /****************************************************************************
55 Returns TRUE iff any adjacent tile contains a base with the given flag
56 (does not check ptile itself)
57 ****************************************************************************/
is_base_flag_near_tile(const struct tile * ptile,enum base_flag_id flag)58 bool is_base_flag_near_tile(const struct tile *ptile, enum base_flag_id flag)
59 {
60 extra_type_by_cause_iterate(EC_BASE, pextra) {
61 if (base_has_flag(extra_base_get(pextra), flag)) {
62 adjc_iterate(ptile, adjc_tile) {
63 if (tile_has_extra(adjc_tile, pextra)) {
64 return TRUE;
65 }
66 } adjc_iterate_end;
67 }
68 } extra_type_by_cause_iterate_end;
69
70 return FALSE;
71 }
72
73 /****************************************************************************
74 Is tile native to base?
75 ****************************************************************************/
is_native_tile_to_base(const struct base_type * pbase,const struct tile * ptile)76 bool is_native_tile_to_base(const struct base_type *pbase,
77 const struct tile *ptile)
78 {
79 struct extra_type *pextra;
80
81 pextra = base_extra_get(pbase);
82
83 return are_reqs_active(NULL, NULL, NULL, NULL, ptile,
84 NULL, NULL, NULL, NULL,
85 &pextra->reqs, RPT_POSSIBLE);
86 }
87
88 /****************************************************************************
89 Base provides base flag for unit? Checks if base provides flag and if
90 base is native to unit.
91 ****************************************************************************/
base_has_flag_for_utype(const struct base_type * pbase,enum base_flag_id flag,const struct unit_type * punittype)92 bool base_has_flag_for_utype(const struct base_type *pbase,
93 enum base_flag_id flag,
94 const struct unit_type *punittype)
95 {
96 return base_has_flag(pbase, flag)
97 && is_native_extra_to_utype(base_extra_get(pbase), punittype);
98 }
99
100 /**************************************************************************
101 Can unit build base to given tile?
102 **************************************************************************/
base_can_be_built(const struct base_type * pbase,const struct tile * ptile)103 bool base_can_be_built(const struct base_type *pbase,
104 const struct tile *ptile)
105 {
106 if (tile_terrain(ptile)->base_time == 0) {
107 /* Bases cannot be built on this terrain. */
108 return FALSE;
109 }
110
111 if (!(base_extra_get(pbase)->buildable)) {
112 /* Base type not buildable. */
113 return FALSE;
114 }
115
116 if (tile_has_base(ptile, pbase)) {
117 /* Exist already */
118 return FALSE;
119 }
120
121 if (tile_city(ptile) != NULL && pbase->border_sq >= 0) {
122 return FALSE;
123 }
124
125 return TRUE;
126 }
127
128 /****************************************************************************
129 Tells if player can build base to tile with suitable unit.
130 ****************************************************************************/
player_can_build_base(const struct base_type * pbase,const struct player * pplayer,const struct tile * ptile)131 bool player_can_build_base(const struct base_type *pbase,
132 const struct player *pplayer,
133 const struct tile *ptile)
134 {
135 struct extra_type *pextra;
136
137 if (!base_can_be_built(pbase, ptile)) {
138 return FALSE;
139 }
140
141 pextra = base_extra_get(pbase);
142
143 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
144 NULL, NULL, NULL, NULL,
145 &pextra->reqs, RPT_POSSIBLE);
146 }
147
148 /**************************************************************************
149 Can unit build base to given tile?
150 **************************************************************************/
can_build_base(const struct unit * punit,const struct base_type * pbase,const struct tile * ptile)151 bool can_build_base(const struct unit *punit, const struct base_type *pbase,
152 const struct tile *ptile)
153 {
154 struct extra_type *pextra;
155
156 if (!base_can_be_built(pbase, ptile)) {
157 return FALSE;
158 }
159
160 pextra = base_extra_get(pbase);
161
162 return are_reqs_active(unit_owner(punit), tile_owner(ptile), NULL, NULL,
163 ptile, punit, unit_type_get(punit), NULL, NULL,
164 &pextra->reqs, RPT_CERTAIN);
165 }
166
167 /****************************************************************************
168 Returns base_type entry for an ID value.
169 ****************************************************************************/
base_by_number(const Base_type_id id)170 struct base_type *base_by_number(const Base_type_id id)
171 {
172 struct extra_type_list *bases;
173
174 bases = extra_type_list_by_cause(EC_BASE);
175
176 if (bases == NULL || id < 0 || id >= extra_type_list_size(bases)) {
177 return NULL;
178 }
179
180 return extra_base_get(extra_type_list_get(bases, id));
181 }
182
183 /**************************************************************************
184 Return the base index.
185 **************************************************************************/
base_number(const struct base_type * pbase)186 Base_type_id base_number(const struct base_type *pbase)
187 {
188 fc_assert_ret_val(NULL != pbase, -1);
189 return pbase->item_number;
190 }
191
192 /**************************************************************************
193 Return the base index.
194
195 Currently same as base_number(), paired with base_count()
196 indicates use as an array index.
197 **************************************************************************/
base_index(const struct base_type * pbase)198 Base_type_id base_index(const struct base_type *pbase)
199 {
200 fc_assert_ret_val(NULL != pbase, -1);
201
202 /* FIXME: */
203 /* return pbase - base_types; */
204 return base_number(pbase);
205 }
206
207 /**************************************************************************
208 Return extra that base is.
209 **************************************************************************/
base_extra_get(const struct base_type * pbase)210 struct extra_type *base_extra_get(const struct base_type *pbase)
211 {
212 return pbase->self;
213 }
214
215 /**************************************************************************
216 Return the number of base_types.
217 **************************************************************************/
base_count(void)218 Base_type_id base_count(void)
219 {
220 return game.control.num_base_types;
221 }
222
223 /****************************************************************************
224 Initialize base_type structures.
225 ****************************************************************************/
base_type_init(struct extra_type * pextra,int idx)226 void base_type_init(struct extra_type *pextra, int idx)
227 {
228 struct base_type *pbase;
229
230 pbase = fc_malloc(sizeof(*pbase));
231
232 pextra->data.base = pbase;
233
234 pbase->item_number = idx;
235 pbase->self = pextra;
236 }
237
238 /****************************************************************************
239 Free the memory associated with base types
240 ****************************************************************************/
base_types_free(void)241 void base_types_free(void)
242 {
243 }
244
245 /**************************************************************************
246 Get best gui_type base for given parameters
247 **************************************************************************/
get_base_by_gui_type(enum base_gui_type type,const struct unit * punit,const struct tile * ptile)248 struct base_type *get_base_by_gui_type(enum base_gui_type type,
249 const struct unit *punit,
250 const struct tile *ptile)
251 {
252 extra_type_by_cause_iterate(EC_BASE, pextra) {
253 struct base_type *pbase = extra_base_get(pextra);
254
255 if (type == pbase->gui_type
256 && (punit == NULL || can_build_base(punit, pbase, ptile))) {
257 return pbase;
258 }
259 } extra_type_by_cause_iterate_end;
260
261 return NULL;
262 }
263
264 /**************************************************************************
265 Does this base type claim territory?
266 **************************************************************************/
territory_claiming_base(const struct base_type * pbase)267 bool territory_claiming_base(const struct base_type *pbase)
268 {
269 return pbase->border_sq >= 0;
270 }
271