Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / road.c
blobe0cc0f58ae972c2f198d9b1bdd7b11ee68705299
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.
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 ****************************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* common */
19 #include "extras.h"
20 #include "fc_types.h"
21 #include "game.h"
22 #include "map.h"
23 #include "movement.h"
24 #include "name_translation.h"
25 #include "unittype.h"
27 #include "road.h"
29 /**************************************************************************
30 Return the road id.
31 **************************************************************************/
32 Road_type_id road_number(const struct road_type *proad)
34 fc_assert_ret_val(NULL != proad, -1);
36 return proad->id;
39 /**************************************************************************
40 Return extra that road is.
41 **************************************************************************/
42 struct extra_type *road_extra_get(const struct road_type *proad)
44 return proad->self;
47 /**************************************************************************
48 Return the number of road_types.
49 **************************************************************************/
50 Road_type_id road_count(void)
52 return game.control.num_road_types;
55 /****************************************************************************
56 Return road type of given id.
57 ****************************************************************************/
58 struct road_type *road_by_number(Road_type_id id)
60 struct extra_type_list *roads;
62 roads = extra_type_list_by_cause(EC_ROAD);
64 if (roads == NULL || id < 0 || id >= extra_type_list_size(roads)) {
65 return NULL;
68 return extra_road_get(extra_type_list_get(roads, id));
71 /****************************************************************************
72 This function is passed to road_type_list_sort() to sort a list of roads
73 in ascending move_cost (faster roads first).
74 ****************************************************************************/
75 int compare_road_move_cost(const struct extra_type *const *p,
76 const struct extra_type *const *q)
78 const struct road_type *proad = extra_road_get(*p);
79 const struct road_type *qroad = extra_road_get(*q);
81 if (proad->move_cost > qroad->move_cost) {
82 return -1; /* q is faster */
83 } else if (proad->move_cost == qroad->move_cost) {
84 return 0;
85 } else {
86 return 1; /* p is faster */
90 /****************************************************************************
91 Initialize road_type structures.
92 ****************************************************************************/
93 void road_type_init(struct extra_type *pextra, int idx)
95 struct road_type *proad;
97 proad = fc_malloc(sizeof(*proad));
99 pextra->data.road = proad;
101 requirement_vector_init(&proad->first_reqs);
103 proad->id = idx;
104 proad->integrators = NULL;
105 proad->self = pextra;
108 /****************************************************************************
109 Initialize the road integrators cache
110 ****************************************************************************/
111 void road_integrators_cache_init(void)
113 extra_type_by_cause_iterate(EC_ROAD, pextra) {
114 struct road_type *proad = extra_road_get(pextra);
116 proad->integrators = extra_type_list_new();
117 /* Roads always integrate with themselves. */
118 extra_type_list_append(proad->integrators, pextra);
119 extra_type_by_cause_iterate(EC_ROAD, oextra) {
120 struct road_type *oroad = extra_road_get(oextra);
122 if (BV_ISSET(proad->integrates, road_number(oroad))) {
123 extra_type_list_append(proad->integrators, oextra);
125 } extra_type_by_cause_iterate_end;
126 extra_type_list_unique(proad->integrators);
127 extra_type_list_sort(proad->integrators, &compare_road_move_cost);
128 } extra_type_by_cause_iterate_end;
131 /****************************************************************************
132 Free the memory associated with road types
133 ****************************************************************************/
134 void road_types_free(void)
136 extra_type_by_cause_iterate(EC_ROAD, pextra) {
137 struct road_type *proad = extra_road_get(pextra);
139 requirement_vector_free(&proad->first_reqs);
141 if (proad->integrators != NULL) {
142 extra_type_list_destroy(proad->integrators);
143 proad->integrators = NULL;
145 } extra_type_by_cause_iterate_end;
148 /****************************************************************************
149 Return tile special that used to represent this road type.
150 ****************************************************************************/
151 enum road_compat road_compat_special(const struct road_type *proad)
153 return proad->compat;
156 /****************************************************************************
157 Return road type represented by given compatibility special, or NULL if
158 special does not represent road type at all.
159 ****************************************************************************/
160 struct road_type *road_by_compat_special(enum road_compat compat)
162 if (compat == ROCO_NONE) {
163 return NULL;
166 extra_type_by_cause_iterate(EC_ROAD, pextra) {
167 struct road_type *proad = extra_road_get(pextra);
168 if (road_compat_special(proad) == compat) {
169 return proad;
171 } extra_type_by_cause_iterate_end;
173 return NULL;
176 /****************************************************************************
177 Tells if road can build to tile if all other requirements are met.
178 ****************************************************************************/
179 bool road_can_be_built(const struct road_type *proad, const struct tile *ptile)
182 if (!(road_extra_get(proad)->buildable)) {
183 /* Road type not buildable. */
184 return FALSE;
187 if (tile_has_road(ptile, proad)) {
188 /* Road exist already */
189 return FALSE;
192 if (tile_terrain(ptile)->road_time == 0) {
193 return FALSE;
196 return TRUE;
199 /****************************************************************************
200 Tells if player can build road to tile with suitable unit.
201 ****************************************************************************/
202 bool can_build_road_base(const struct road_type *proad,
203 const struct player *pplayer,
204 const struct tile *ptile)
206 if (!road_can_be_built(proad, ptile)) {
207 return FALSE;
210 if (road_has_flag(proad, RF_REQUIRES_BRIDGE)
211 && !player_knows_techs_with_flag(pplayer, TF_BRIDGE)) {
212 /* TODO: Cache list of road types with RF_PREVENTS_OTHER_ROADS
213 * after ruleset loading and use that list here instead
214 * of always iterating through all road types. */
215 extra_type_by_cause_iterate(EC_ROAD, poextra) {
216 struct road_type *old = extra_road_get(poextra);
218 if (road_has_flag(old, RF_PREVENTS_OTHER_ROADS)
219 && tile_has_extra(ptile, poextra)) {
220 return FALSE;
222 } extra_type_by_cause_iterate_end;
225 return TRUE;
228 /****************************************************************************
229 Tells if player and optionally unit have road building requirements
230 fulfilled.
231 ****************************************************************************/
232 static bool are_road_reqs_fulfilled(const struct road_type *proad,
233 const struct player *pplayer,
234 const struct unit *punit,
235 const struct tile *ptile)
237 struct extra_type *pextra = road_extra_get(proad);
238 const struct unit_type *utype;
240 if (punit == NULL) {
241 utype = NULL;
242 } else {
243 utype = unit_type_get(punit);
246 if (requirement_vector_size(&proad->first_reqs) > 0) {
247 bool beginning = TRUE;
249 extra_type_list_iterate(proad->integrators, iroad) {
250 /* FIXME: mixing cardinal and non-cardinal roads as integrators is
251 * probably not a good idea. */
252 if (is_cardinal_only_road(iroad)) {
253 cardinal_adjc_iterate(ptile, adjc_tile) {
254 if (tile_has_extra(adjc_tile, iroad)) {
255 beginning = FALSE;
256 break;
258 } cardinal_adjc_iterate_end;
259 } else {
260 adjc_iterate(ptile, adjc_tile) {
261 if (tile_has_extra(adjc_tile, iroad)) {
262 beginning = FALSE;
263 break;
265 } adjc_iterate_end;
268 if (!beginning) {
269 break;
271 } extra_type_list_iterate_end;
273 if (beginning) {
274 if (!are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
275 punit, utype, NULL, NULL, NULL,
276 &proad->first_reqs, RPT_POSSIBLE)) {
277 return FALSE;
282 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
283 punit, utype, NULL, NULL, NULL,
284 &pextra->reqs, RPT_POSSIBLE);
287 /****************************************************************************
288 Tells if player can build road to tile with suitable unit.
289 ****************************************************************************/
290 bool player_can_build_road(const struct road_type *proad,
291 const struct player *pplayer,
292 const struct tile *ptile)
294 if (!can_build_road_base(proad, pplayer, ptile)) {
295 return FALSE;
298 return are_road_reqs_fulfilled(proad, pplayer, NULL, ptile);
301 /****************************************************************************
302 Tells if unit can build road on tile.
303 ****************************************************************************/
304 bool can_build_road(struct road_type *proad,
305 const struct unit *punit,
306 const struct tile *ptile)
308 struct player *pplayer = unit_owner(punit);
310 if (!can_build_road_base(proad, pplayer, ptile)) {
311 return FALSE;
314 return are_road_reqs_fulfilled(proad, pplayer, punit, ptile);
317 /****************************************************************************
318 Count tiles with specified road near the tile. Can be called with NULL
319 road.
320 ****************************************************************************/
321 int count_road_near_tile(const struct tile *ptile, const struct road_type *proad)
323 int count = 0;
325 if (proad == NULL) {
326 return 0;
329 adjc_iterate(ptile, adjc_tile) {
330 if (tile_has_road(adjc_tile, proad)) {
331 count++;
333 } adjc_iterate_end;
335 return count;
338 /****************************************************************************
339 Count tiles with any river near the tile.
340 ****************************************************************************/
341 int count_river_near_tile(const struct tile *ptile,
342 const struct extra_type *priver)
344 int count = 0;
346 cardinal_adjc_iterate(ptile, adjc_tile) {
347 if (priver == NULL && tile_has_river(adjc_tile)) {
348 /* Some river */
349 count++;
350 } else if (priver != NULL && tile_has_extra(adjc_tile, priver)) {
351 /* Specific river */
352 count++;
354 } cardinal_adjc_iterate_end;
356 return count;
359 /****************************************************************************
360 Count tiles with river of specific type cardinally adjacent to the tile.
361 ****************************************************************************/
362 int count_river_type_tile_card(const struct tile *ptile,
363 const struct extra_type *priver,
364 bool percentage)
366 int count = 0;
367 int total = 0;
369 fc_assert(priver != NULL);
371 cardinal_adjc_iterate(ptile, adjc_tile) {
372 if (tile_has_extra(adjc_tile, priver)) {
373 count++;
375 total++;
376 } cardinal_adjc_iterate_end;
378 if (percentage) {
379 count = count * 100 / total;
381 return count;
384 /****************************************************************************
385 Count tiles with river of specific type near the tile.
386 ****************************************************************************/
387 int count_river_type_near_tile(const struct tile *ptile,
388 const struct extra_type *priver,
389 bool percentage)
391 int count = 0;
392 int total = 0;
394 fc_assert(priver != NULL);
396 adjc_iterate(ptile, adjc_tile) {
397 if (tile_has_extra(adjc_tile, priver)) {
398 count++;
400 total++;
401 } adjc_iterate_end;
403 if (percentage) {
404 count = count * 100 / total;
406 return count;
409 /****************************************************************************
410 Check if road provides effect
411 ****************************************************************************/
412 bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
414 return BV_ISSET(proad->flags, flag);
417 /****************************************************************************
418 Returns TRUE iff any cardinally adjacent tile contains a road with
419 the given flag (does not check ptile itself).
420 ****************************************************************************/
421 bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
423 extra_type_by_cause_iterate(EC_ROAD, pextra) {
424 if (road_has_flag(extra_road_get(pextra), flag)) {
425 cardinal_adjc_iterate(ptile, adjc_tile) {
426 if (tile_has_extra(adjc_tile, pextra)) {
427 return TRUE;
429 } cardinal_adjc_iterate_end;
431 } extra_type_by_cause_iterate_end;
433 return FALSE;
436 /****************************************************************************
437 Returns TRUE iff any adjacent tile contains a road with the given flag
438 (does not check ptile itself).
439 ****************************************************************************/
440 bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
442 extra_type_by_cause_iterate(EC_ROAD, pextra) {
443 if (road_has_flag(extra_road_get(pextra), flag)) {
444 adjc_iterate(ptile, adjc_tile) {
445 if (tile_has_extra(adjc_tile, pextra)) {
446 return TRUE;
448 } adjc_iterate_end;
450 } extra_type_by_cause_iterate_end;
452 return FALSE;
455 /****************************************************************************
456 Is tile native to road?
457 ****************************************************************************/
458 bool is_native_tile_to_road(const struct road_type *proad,
459 const struct tile *ptile)
461 struct extra_type *pextra;
463 if (road_has_flag(proad, RF_RIVER)) {
464 if (!terrain_has_flag(tile_terrain(ptile), TER_CAN_HAVE_RIVER)) {
465 return FALSE;
467 } else if (tile_terrain(ptile)->road_time == 0) {
468 return FALSE;
471 pextra = road_extra_get(proad);
473 return are_reqs_active(NULL, NULL, NULL, NULL, ptile,
474 NULL, NULL, NULL, NULL, NULL,
475 &pextra->reqs, RPT_POSSIBLE);
478 /****************************************************************************
479 Is extra cardinal only road.
480 ****************************************************************************/
481 bool is_cardinal_only_road(const struct extra_type *pextra)
483 const struct road_type *proad;
485 if (!is_extra_caused_by(pextra, EC_ROAD)) {
486 return FALSE;
489 proad = extra_road_get(pextra);
491 return proad->move_mode == RMM_CARDINAL || proad->move_mode == RMM_RELAXED;
494 /****************************************************************************
495 Does road type provide move bonus
496 ****************************************************************************/
497 bool road_provides_move_bonus(const struct road_type *proad)
499 return proad->move_cost >= 0;