Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / common / road.c
blob8577ba492e594a896a3612dd082ae54562ff94dd
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 /* FIXME: mixing cardinal and non-cardinal roads as integrators is
266 * probably not a good idea. */
267 if (is_cardinal_only_road(iroad)) {
268 cardinal_adjc_iterate(ptile, adjc_tile) {
269 if (tile_has_extra(adjc_tile, iroad)) {
270 beginning = FALSE;
271 break;
273 } cardinal_adjc_iterate_end;
274 } else {
275 adjc_iterate(ptile, adjc_tile) {
276 if (tile_has_extra(adjc_tile, iroad)) {
277 beginning = FALSE;
278 break;
280 } adjc_iterate_end;
283 if (!beginning) {
284 break;
286 } extra_type_list_iterate_end;
288 if (beginning) {
289 if (!are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
290 punit, utype, NULL, NULL,
291 &proad->first_reqs, RPT_POSSIBLE)) {
292 return FALSE;
297 return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
298 punit, utype, NULL, NULL, &pextra->reqs,
299 RPT_POSSIBLE);
302 /****************************************************************************
303 Tells if player can build road to tile with suitable unit.
304 ****************************************************************************/
305 bool player_can_build_road(const struct road_type *proad,
306 const struct player *pplayer,
307 const struct tile *ptile)
309 if (!can_build_road_base(proad, pplayer, ptile)) {
310 return FALSE;
313 return are_road_reqs_fulfilled(proad, pplayer, NULL, ptile);
316 /****************************************************************************
317 Tells if unit can build road on tile.
318 ****************************************************************************/
319 bool can_build_road(struct road_type *proad,
320 const struct unit *punit,
321 const struct tile *ptile)
323 struct player *pplayer = unit_owner(punit);
325 if (!can_build_road_base(proad, pplayer, ptile)) {
326 return FALSE;
329 return are_road_reqs_fulfilled(proad, pplayer, punit, ptile);
332 /****************************************************************************
333 Count tiles with specified road near the tile. Can be called with NULL
334 road.
335 ****************************************************************************/
336 int count_road_near_tile(const struct tile *ptile, const struct road_type *proad)
338 int count = 0;
340 if (proad == NULL) {
341 return 0;
344 adjc_iterate(ptile, adjc_tile) {
345 if (tile_has_road(adjc_tile, proad)) {
346 count++;
348 } adjc_iterate_end;
350 return count;
353 /****************************************************************************
354 Count tiles with any river near the tile.
355 ****************************************************************************/
356 int count_river_near_tile(const struct tile *ptile,
357 const struct extra_type *priver)
359 int count = 0;
361 cardinal_adjc_iterate(ptile, adjc_tile) {
362 if (priver == NULL && tile_has_river(adjc_tile)) {
363 /* Some river */
364 count++;
365 } else if (priver != NULL && tile_has_extra(adjc_tile, priver)) {
366 /* Specific river */
367 count++;
369 } cardinal_adjc_iterate_end;
371 return count;
374 /****************************************************************************
375 Count tiles with river of specific type cardinally adjacent to the tile.
376 ****************************************************************************/
377 int count_river_type_tile_card(const struct tile *ptile,
378 const struct extra_type *priver,
379 bool percentage)
381 int count = 0;
382 int total = 0;
384 fc_assert(priver != NULL);
386 cardinal_adjc_iterate(ptile, adjc_tile) {
387 if (tile_has_extra(adjc_tile, priver)) {
388 count++;
390 total++;
391 } cardinal_adjc_iterate_end;
393 if (percentage) {
394 count = count * 100 / total;
396 return count;
399 /****************************************************************************
400 Count tiles with river of specific type near the tile.
401 ****************************************************************************/
402 int count_river_type_near_tile(const struct tile *ptile,
403 const struct extra_type *priver,
404 bool percentage)
406 int count = 0;
407 int total = 0;
409 fc_assert(priver != NULL);
411 adjc_iterate(ptile, adjc_tile) {
412 if (tile_has_extra(adjc_tile, priver)) {
413 count++;
415 total++;
416 } adjc_iterate_end;
418 if (percentage) {
419 count = count * 100 / total;
421 return count;
424 /****************************************************************************
425 Check if road provides effect
426 ****************************************************************************/
427 bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
429 return BV_ISSET(proad->flags, flag);
432 /****************************************************************************
433 Returns TRUE iff any cardinally adjacent tile contains a road with
434 the given flag (does not check ptile itself).
435 ****************************************************************************/
436 bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
438 extra_type_by_cause_iterate(EC_ROAD, pextra) {
439 if (road_has_flag(extra_road_get(pextra), flag)) {
440 cardinal_adjc_iterate(ptile, adjc_tile) {
441 if (tile_has_extra(adjc_tile, pextra)) {
442 return TRUE;
444 } cardinal_adjc_iterate_end;
446 } extra_type_by_cause_iterate_end;
448 return FALSE;
451 /****************************************************************************
452 Returns TRUE iff any adjacent tile contains a road with the given flag
453 (does not check ptile itself).
454 ****************************************************************************/
455 bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
457 extra_type_by_cause_iterate(EC_ROAD, pextra) {
458 if (road_has_flag(extra_road_get(pextra), flag)) {
459 adjc_iterate(ptile, adjc_tile) {
460 if (tile_has_extra(adjc_tile, pextra)) {
461 return TRUE;
463 } adjc_iterate_end;
465 } extra_type_by_cause_iterate_end;
467 return FALSE;
470 /****************************************************************************
471 Is tile native to road?
472 ****************************************************************************/
473 bool is_native_tile_to_road(const struct road_type *proad,
474 const struct tile *ptile)
476 struct extra_type *pextra;
478 if (road_has_flag(proad, RF_RIVER)) {
479 if (!terrain_has_flag(tile_terrain(ptile), TER_CAN_HAVE_RIVER)) {
480 return FALSE;
482 } else if (tile_terrain(ptile)->road_time == 0) {
483 return FALSE;
486 pextra = road_extra_get(proad);
488 return are_reqs_active(NULL, NULL, NULL, NULL, ptile,
489 NULL, NULL, NULL, NULL,
490 &pextra->reqs, RPT_POSSIBLE);
493 /****************************************************************************
494 Is extra cardinal only road.
495 ****************************************************************************/
496 bool is_cardinal_only_road(const struct extra_type *pextra)
498 const struct road_type *proad;
500 if (!is_extra_caused_by(pextra, EC_ROAD)) {
501 return FALSE;
504 proad = extra_road_get(pextra);
506 return proad->move_mode == RMM_CARDINAL || proad->move_mode == RMM_RELAXED;
509 /****************************************************************************
510 Does road type provide move bonus
511 ****************************************************************************/
512 bool road_provides_move_bonus(const struct road_type *proad)
514 return proad->move_cost >= 0;