Prevented building advisor from randomly building, and thus potentially just moving...
[freeciv.git] / common / road.c
blob1a7684cf87dbed7bb63bf67dc42c6676c35c9cc9
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 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);
49 /* FIXME: */
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)
59 return proad->self;
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)) {
80 return NULL;
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) {
99 return 0;
100 } else {
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);
118 proad->id = idx;
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) {
178 return NULL;
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) {
184 return proad;
186 } extra_type_by_cause_iterate_end;
188 return NULL;
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. */
199 return FALSE;
202 if (tile_has_road(ptile, proad)) {
203 /* Road exist already */
204 return FALSE;
207 if (tile_terrain(ptile)->road_time == 0) {
208 return FALSE;
211 return TRUE;
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)) {
222 return FALSE;
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)) {
235 return FALSE;
237 } extra_type_by_cause_iterate_end;
240 return TRUE;
243 /****************************************************************************
244 Tells if player and optionally unit have road building requirements
245 fulfilled.
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;
255 if (punit == NULL) {
256 utype = NULL;
257 } else {
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)) {
267 beginning = FALSE;
268 break;
270 } adjc_iterate_end;
272 if (!beginning) {
273 break;
275 } extra_type_list_iterate_end;
277 if (beginning) {
278 if (!are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
279 punit, utype, NULL, NULL,
280 &proad->first_reqs, RPT_POSSIBLE)) {
281 return FALSE;
286 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
287 punit, utype, NULL, NULL, &pextra->reqs,
288 RPT_POSSIBLE);
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)) {
299 return FALSE;
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)) {
315 return FALSE;
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
323 road.
324 ****************************************************************************/
325 int count_road_near_tile(const struct tile *ptile, const struct road_type *proad)
327 int count = 0;
329 if (proad == NULL) {
330 return 0;
333 adjc_iterate(ptile, adjc_tile) {
334 if (tile_has_road(adjc_tile, proad)) {
335 count++;
337 } adjc_iterate_end;
339 return count;
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)
348 int count = 0;
350 cardinal_adjc_iterate(ptile, adjc_tile) {
351 if (priver == NULL && tile_has_river(adjc_tile)) {
352 /* Some river */
353 count++;
354 } else if (priver != NULL && tile_has_extra(adjc_tile, priver)) {
355 /* Specific river */
356 count++;
358 } cardinal_adjc_iterate_end;
360 return count;
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,
368 bool percentage)
370 int count = 0;
371 int total = 0;
373 fc_assert(priver != NULL);
375 cardinal_adjc_iterate(ptile, adjc_tile) {
376 if (tile_has_extra(adjc_tile, priver)) {
377 count++;
379 total++;
380 } cardinal_adjc_iterate_end;
382 if (percentage) {
383 count = count * 100 / total;
385 return count;
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,
393 bool percentage)
395 int count = 0;
396 int total = 0;
398 fc_assert(priver != NULL);
400 adjc_iterate(ptile, adjc_tile) {
401 if (tile_has_extra(adjc_tile, priver)) {
402 count++;
404 total++;
405 } adjc_iterate_end;
407 if (percentage) {
408 count = count * 100 / total;
410 return count;
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)) {
431 return TRUE;
433 } cardinal_adjc_iterate_end;
435 } extra_type_by_cause_iterate_end;
437 return FALSE;
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)) {
450 return TRUE;
452 } adjc_iterate_end;
454 } extra_type_by_cause_iterate_end;
456 return FALSE;
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)) {
469 return FALSE;
471 } else if (tile_terrain(ptile)->road_time == 0) {
472 return FALSE;
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)) {
490 return FALSE;
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;