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)
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 ****************************************************************************/
15 #include <fc_config.h>
24 #include "name_translation.h"
29 /**************************************************************************
31 **************************************************************************/
32 Road_type_id
road_number(const struct road_type
*proad
)
34 fc_assert_ret_val(NULL
!= proad
, -1);
39 /**************************************************************************
40 Return extra that road is.
41 **************************************************************************/
42 struct extra_type
*road_extra_get(const struct road_type
*proad
)
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
)) {
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
) {
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
);
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
) {
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
) {
171 } extra_type_by_cause_iterate_end
;
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. */
187 if (tile_has_road(ptile
, proad
)) {
188 /* Road exist already */
192 if (tile_terrain(ptile
)->road_time
== 0) {
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
)) {
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
)) {
222 } extra_type_by_cause_iterate_end
;
228 /****************************************************************************
229 Tells if player and optionally unit have road building requirements
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
;
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
)) {
258 } cardinal_adjc_iterate_end
;
260 adjc_iterate(ptile
, adjc_tile
) {
261 if (tile_has_extra(adjc_tile
, iroad
)) {
271 } extra_type_list_iterate_end
;
274 if (!are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
275 punit
, utype
, NULL
, NULL
, NULL
,
276 &proad
->first_reqs
, RPT_POSSIBLE
)) {
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
)) {
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
)) {
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
320 ****************************************************************************/
321 int count_road_near_tile(const struct tile
*ptile
, const struct road_type
*proad
)
329 adjc_iterate(ptile
, adjc_tile
) {
330 if (tile_has_road(adjc_tile
, proad
)) {
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
)
346 cardinal_adjc_iterate(ptile
, adjc_tile
) {
347 if (priver
== NULL
&& tile_has_river(adjc_tile
)) {
350 } else if (priver
!= NULL
&& tile_has_extra(adjc_tile
, priver
)) {
354 } cardinal_adjc_iterate_end
;
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
,
369 fc_assert(priver
!= NULL
);
371 cardinal_adjc_iterate(ptile
, adjc_tile
) {
372 if (tile_has_extra(adjc_tile
, priver
)) {
376 } cardinal_adjc_iterate_end
;
379 count
= count
* 100 / total
;
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
,
394 fc_assert(priver
!= NULL
);
396 adjc_iterate(ptile
, adjc_tile
) {
397 if (tile_has_extra(adjc_tile
, priver
)) {
404 count
= count
* 100 / total
;
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
)) {
429 } cardinal_adjc_iterate_end
;
431 } extra_type_by_cause_iterate_end
;
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
)) {
450 } extra_type_by_cause_iterate_end
;
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
)) {
467 } else if (tile_terrain(ptile
)->road_time
== 0) {
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
)) {
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;