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