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 the road index.
42 Currently same as road_number(), paired with road_count()
43 indicates use as an array index.
44 **************************************************************************/
45 Road_type_id
road_index(const struct road_type
*proad
)
47 fc_assert_ret_val(NULL
!= proad
, -1);
50 /* return proad - roads; */
51 return road_number(proad
);
54 /**************************************************************************
55 Return extra that road is.
56 **************************************************************************/
57 struct extra_type
*road_extra_get(const struct road_type
*proad
)
62 /**************************************************************************
63 Return the number of road_types.
64 **************************************************************************/
65 Road_type_id
road_count(void)
67 return game
.control
.num_road_types
;
70 /****************************************************************************
71 Return road type of given id.
72 ****************************************************************************/
73 struct road_type
*road_by_number(Road_type_id id
)
75 struct extra_type_list
*roads
;
77 roads
= extra_type_list_by_cause(EC_ROAD
);
79 if (roads
== NULL
|| id
< 0 || id
>= extra_type_list_size(roads
)) {
83 return extra_road_get(extra_type_list_get(roads
, id
));
86 /****************************************************************************
87 This function is passed to road_type_list_sort() to sort a list of roads
88 in ascending move_cost (faster roads first).
89 ****************************************************************************/
90 int compare_road_move_cost(const struct extra_type
*const *p
,
91 const struct extra_type
*const *q
)
93 const struct road_type
*proad
= extra_road_get(*p
);
94 const struct road_type
*qroad
= extra_road_get(*q
);
96 if (proad
->move_cost
> qroad
->move_cost
) {
97 return -1; /* q is faster */
98 } else if (proad
->move_cost
== qroad
->move_cost
) {
101 return 1; /* p is faster */
105 /****************************************************************************
106 Initialize road_type structures.
107 ****************************************************************************/
108 void road_type_init(struct extra_type
*pextra
, int idx
)
110 struct road_type
*proad
;
112 proad
= fc_malloc(sizeof(*proad
));
114 pextra
->data
.road
= proad
;
116 requirement_vector_init(&proad
->first_reqs
);
119 proad
->integrators
= NULL
;
120 proad
->self
= pextra
;
124 /****************************************************************************
125 Initialize the road integrators cache
126 ****************************************************************************/
127 void road_integrators_cache_init(void)
129 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
130 struct road_type
*proad
= extra_road_get(pextra
);
132 proad
->integrators
= extra_type_list_new();
133 /* Roads always integrate with themselves. */
134 extra_type_list_append(proad
->integrators
, pextra
);
135 extra_type_by_cause_iterate(EC_ROAD
, oextra
) {
136 struct road_type
*oroad
= extra_road_get(oextra
);
137 if (BV_ISSET(proad
->integrates
, road_index(oroad
))) {
138 extra_type_list_append(proad
->integrators
, oextra
);
140 } extra_type_by_cause_iterate_end
;
141 extra_type_list_unique(proad
->integrators
);
142 extra_type_list_sort(proad
->integrators
, &compare_road_move_cost
);
143 } extra_type_by_cause_iterate_end
;
146 /****************************************************************************
147 Free the memory associated with road types
148 ****************************************************************************/
149 void road_types_free(void)
151 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
152 struct road_type
*proad
= extra_road_get(pextra
);
154 requirement_vector_free(&proad
->first_reqs
);
156 if (proad
->integrators
!= NULL
) {
157 extra_type_list_destroy(proad
->integrators
);
158 proad
->integrators
= NULL
;
160 } extra_type_by_cause_iterate_end
;
163 /****************************************************************************
164 Return tile special that used to represent this road type.
165 ****************************************************************************/
166 enum road_compat
road_compat_special(const struct road_type
*proad
)
168 return proad
->compat
;
171 /****************************************************************************
172 Return road type represented by given compatibility special, or NULL if
173 special does not represent road type at all.
174 ****************************************************************************/
175 struct road_type
*road_by_compat_special(enum road_compat compat
)
177 if (compat
== ROCO_NONE
) {
181 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
182 struct road_type
*proad
= extra_road_get(pextra
);
183 if (road_compat_special(proad
) == compat
) {
186 } extra_type_by_cause_iterate_end
;
191 /****************************************************************************
192 Tells if road can build to tile if all other requirements are met.
193 ****************************************************************************/
194 bool road_can_be_built(const struct road_type
*proad
, const struct tile
*ptile
)
197 if (!(road_extra_get(proad
)->buildable
)) {
198 /* Road type not buildable. */
202 if (tile_has_road(ptile
, proad
)) {
203 /* Road exist already */
207 if (tile_terrain(ptile
)->road_time
== 0) {
214 /****************************************************************************
215 Tells if player can build road to tile with suitable unit.
216 ****************************************************************************/
217 bool can_build_road_base(const struct road_type
*proad
,
218 const struct player
*pplayer
,
219 const struct tile
*ptile
)
221 if (!road_can_be_built(proad
, ptile
)) {
225 if (road_has_flag(proad
, RF_REQUIRES_BRIDGE
)
226 && !player_knows_techs_with_flag(pplayer
, TF_BRIDGE
)) {
227 /* TODO: Cache list of road types with RF_PREVENTS_OTHER_ROADS
228 * after ruleset loading and use that list here instead
229 * of always iterating through all road types. */
230 extra_type_by_cause_iterate(EC_ROAD
, poextra
) {
231 struct road_type
*old
= extra_road_get(poextra
);
233 if (road_has_flag(old
, RF_PREVENTS_OTHER_ROADS
)
234 && tile_has_extra(ptile
, poextra
)) {
237 } extra_type_by_cause_iterate_end
;
243 /****************************************************************************
244 Tells if player and optionally unit have road building requirements
246 ****************************************************************************/
247 static bool are_road_reqs_fulfilled(const struct road_type
*proad
,
248 const struct player
*pplayer
,
249 const struct unit
*punit
,
250 const struct tile
*ptile
)
252 struct extra_type
*pextra
= road_extra_get(proad
);
253 const struct unit_type
*utype
;
258 utype
= unit_type_get(punit
);
261 if (requirement_vector_size(&proad
->first_reqs
) > 0) {
262 bool beginning
= TRUE
;
264 extra_type_list_iterate(proad
->integrators
, iroad
) {
265 adjc_iterate(ptile
, adjc_tile
) {
266 if (tile_has_extra(adjc_tile
, iroad
)) {
275 } extra_type_list_iterate_end
;
278 if (!are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
279 punit
, utype
, NULL
, NULL
,
280 &proad
->first_reqs
, RPT_POSSIBLE
)) {
286 return are_reqs_active(pplayer
, tile_owner(ptile
), NULL
, NULL
, ptile
,
287 punit
, utype
, NULL
, NULL
, &pextra
->reqs
,
291 /****************************************************************************
292 Tells if player can build road to tile with suitable unit.
293 ****************************************************************************/
294 bool player_can_build_road(const struct road_type
*proad
,
295 const struct player
*pplayer
,
296 const struct tile
*ptile
)
298 if (!can_build_road_base(proad
, pplayer
, ptile
)) {
302 return are_road_reqs_fulfilled(proad
, pplayer
, NULL
, ptile
);
305 /****************************************************************************
306 Tells if unit can build road on tile.
307 ****************************************************************************/
308 bool can_build_road(struct road_type
*proad
,
309 const struct unit
*punit
,
310 const struct tile
*ptile
)
312 struct player
*pplayer
= unit_owner(punit
);
314 if (!can_build_road_base(proad
, pplayer
, ptile
)) {
318 return are_road_reqs_fulfilled(proad
, pplayer
, punit
, ptile
);
321 /****************************************************************************
322 Count tiles with specified road near the tile. Can be called with NULL
324 ****************************************************************************/
325 int count_road_near_tile(const struct tile
*ptile
, const struct road_type
*proad
)
333 adjc_iterate(ptile
, adjc_tile
) {
334 if (tile_has_road(adjc_tile
, proad
)) {
342 /****************************************************************************
343 Count tiles with any river near the tile.
344 ****************************************************************************/
345 int count_river_near_tile(const struct tile
*ptile
,
346 const struct extra_type
*priver
)
350 cardinal_adjc_iterate(ptile
, adjc_tile
) {
351 if (priver
== NULL
&& tile_has_river(adjc_tile
)) {
354 } else if (priver
!= NULL
&& tile_has_extra(adjc_tile
, priver
)) {
358 } cardinal_adjc_iterate_end
;
363 /****************************************************************************
364 Count tiles with river of specific type cardinally adjacent to the tile.
365 ****************************************************************************/
366 int count_river_type_tile_card(const struct tile
*ptile
,
367 const struct extra_type
*priver
,
373 fc_assert(priver
!= NULL
);
375 cardinal_adjc_iterate(ptile
, adjc_tile
) {
376 if (tile_has_extra(adjc_tile
, priver
)) {
380 } cardinal_adjc_iterate_end
;
383 count
= count
* 100 / total
;
388 /****************************************************************************
389 Count tiles with river of specific type near the tile.
390 ****************************************************************************/
391 int count_river_type_near_tile(const struct tile
*ptile
,
392 const struct extra_type
*priver
,
398 fc_assert(priver
!= NULL
);
400 adjc_iterate(ptile
, adjc_tile
) {
401 if (tile_has_extra(adjc_tile
, priver
)) {
408 count
= count
* 100 / total
;
413 /****************************************************************************
414 Check if road provides effect
415 ****************************************************************************/
416 bool road_has_flag(const struct road_type
*proad
, enum road_flag_id flag
)
418 return BV_ISSET(proad
->flags
, flag
);
421 /****************************************************************************
422 Returns TRUE iff any cardinally adjacent tile contains a road with
423 the given flag (does not check ptile itself).
424 ****************************************************************************/
425 bool is_road_flag_card_near(const struct tile
*ptile
, enum road_flag_id flag
)
427 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
428 if (road_has_flag(extra_road_get(pextra
), flag
)) {
429 cardinal_adjc_iterate(ptile
, adjc_tile
) {
430 if (tile_has_extra(adjc_tile
, pextra
)) {
433 } cardinal_adjc_iterate_end
;
435 } extra_type_by_cause_iterate_end
;
440 /****************************************************************************
441 Returns TRUE iff any adjacent tile contains a road with the given flag
442 (does not check ptile itself).
443 ****************************************************************************/
444 bool is_road_flag_near_tile(const struct tile
*ptile
, enum road_flag_id flag
)
446 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
447 if (road_has_flag(extra_road_get(pextra
), flag
)) {
448 adjc_iterate(ptile
, adjc_tile
) {
449 if (tile_has_extra(adjc_tile
, pextra
)) {
454 } extra_type_by_cause_iterate_end
;
459 /****************************************************************************
460 Is tile native to road?
461 ****************************************************************************/
462 bool is_native_tile_to_road(const struct road_type
*proad
,
463 const struct tile
*ptile
)
465 struct extra_type
*pextra
;
467 if (road_has_flag(proad
, RF_RIVER
)) {
468 if (!terrain_has_flag(tile_terrain(ptile
), TER_CAN_HAVE_RIVER
)) {
471 } else if (tile_terrain(ptile
)->road_time
== 0) {
475 pextra
= road_extra_get(proad
);
477 return are_reqs_active(NULL
, NULL
, NULL
, NULL
, ptile
,
478 NULL
, NULL
, NULL
, NULL
,
479 &pextra
->reqs
, RPT_POSSIBLE
);
482 /****************************************************************************
483 Is extra cardinal only road.
484 ****************************************************************************/
485 bool is_cardinal_only_road(const struct extra_type
*pextra
)
487 const struct road_type
*proad
;
489 if (!is_extra_caused_by(pextra
, EC_ROAD
)) {
493 proad
= extra_road_get(pextra
);
495 return proad
->move_mode
== RMM_CARDINAL
|| proad
->move_mode
== RMM_RELAXED
;
498 /****************************************************************************
499 Does road type provide move bonus
500 ****************************************************************************/
501 bool road_provides_move_bonus(const struct road_type
*proad
)
503 return proad
->move_cost
>= 0;