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.
7 
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 ****************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
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"
26 
27 #include "road.h"
28 
29 /**************************************************************************
30   Return the road id.
31 **************************************************************************/
road_number(const struct road_type * proad)32 Road_type_id road_number(const struct road_type *proad)
33 {
34   fc_assert_ret_val(NULL != proad, -1);
35 
36   return proad->id;
37 }
38 
39 /**************************************************************************
40   Return the road index.
41 
42   Currently same as road_number(), paired with road_count()
43   indicates use as an array index.
44 **************************************************************************/
road_index(const struct road_type * proad)45 Road_type_id road_index(const struct road_type *proad)
46 {
47   fc_assert_ret_val(NULL != proad, -1);
48 
49   /* FIXME: */
50   /* return proad - roads; */
51   return road_number(proad);
52 }
53 
54 /**************************************************************************
55   Return extra that road is.
56 **************************************************************************/
road_extra_get(const struct road_type * proad)57 struct extra_type *road_extra_get(const struct road_type *proad)
58 {
59   return proad->self;
60 }
61 
62 /**************************************************************************
63   Return the number of road_types.
64 **************************************************************************/
road_count(void)65 Road_type_id road_count(void)
66 {
67   return game.control.num_road_types;
68 }
69 
70 /****************************************************************************
71   Return road type of given id.
72 ****************************************************************************/
road_by_number(Road_type_id id)73 struct road_type *road_by_number(Road_type_id id)
74 {
75   struct extra_type_list *roads;
76 
77   roads = extra_type_list_by_cause(EC_ROAD);
78 
79   if (roads == NULL || id < 0 || id >= extra_type_list_size(roads)) {
80     return NULL;
81   }
82 
83   return extra_road_get(extra_type_list_get(roads, id));
84 }
85 
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 ****************************************************************************/
compare_road_move_cost(const struct extra_type * const * p,const struct extra_type * const * q)90 int compare_road_move_cost(const struct extra_type *const *p,
91                            const struct extra_type *const *q)
92 {
93   const struct road_type *proad = extra_road_get(*p);
94   const struct road_type *qroad = extra_road_get(*q);
95 
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 */
102   }
103 }
104 
105 /****************************************************************************
106   Initialize road_type structures.
107 ****************************************************************************/
road_type_init(struct extra_type * pextra,int idx)108 void road_type_init(struct extra_type *pextra, int idx)
109 {
110   struct road_type *proad;
111 
112   proad = fc_malloc(sizeof(*proad));
113 
114   pextra->data.road = proad;
115 
116   requirement_vector_init(&proad->first_reqs);
117 
118   proad->id = idx;
119   proad->integrators = NULL;
120   proad->self = pextra;
121 }
122 
123 
124 /****************************************************************************
125   Initialize the road integrators cache
126 ****************************************************************************/
road_integrators_cache_init(void)127 void road_integrators_cache_init(void)
128 {
129   extra_type_by_cause_iterate(EC_ROAD, pextra) {
130     struct road_type *proad = extra_road_get(pextra);
131 
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);
139       }
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;
144 }
145 
146 /****************************************************************************
147   Free the memory associated with road types
148 ****************************************************************************/
road_types_free(void)149 void road_types_free(void)
150 {
151   extra_type_by_cause_iterate(EC_ROAD, pextra) {
152     struct road_type *proad = extra_road_get(pextra);
153 
154     requirement_vector_free(&proad->first_reqs);
155 
156     if (proad->integrators != NULL) {
157       extra_type_list_destroy(proad->integrators);
158       proad->integrators = NULL;
159     }
160   } extra_type_by_cause_iterate_end;
161 }
162 
163 /****************************************************************************
164   Return tile special that used to represent this road type.
165 ****************************************************************************/
road_compat_special(const struct road_type * proad)166 enum road_compat road_compat_special(const struct road_type *proad)
167 {
168   return proad->compat;
169 }
170 
171 /****************************************************************************
172   Return road type represented by given compatibility special, or NULL if
173   special does not represent road type at all.
174 ****************************************************************************/
road_by_compat_special(enum road_compat compat)175 struct road_type *road_by_compat_special(enum road_compat compat)
176 {
177   if (compat == ROCO_NONE) {
178     return NULL;
179   }
180 
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;
185     }
186   } extra_type_by_cause_iterate_end;
187 
188   return NULL;
189 }
190 
191 /****************************************************************************
192   Tells if road can build to tile if all other requirements are met.
193 ****************************************************************************/
road_can_be_built(const struct road_type * proad,const struct tile * ptile)194 bool road_can_be_built(const struct road_type *proad, const struct tile *ptile)
195 {
196 
197   if (!(road_extra_get(proad)->buildable)) {
198     /* Road type not buildable. */
199     return FALSE;
200   }
201 
202   if (tile_has_road(ptile, proad)) {
203     /* Road exist already */
204     return FALSE;
205   }
206 
207   if (tile_terrain(ptile)->road_time == 0) {
208     return FALSE;
209   }
210 
211   return TRUE;
212 }
213 
214 /****************************************************************************
215   Tells if player can build road to tile with suitable unit.
216 ****************************************************************************/
can_build_road_base(const struct road_type * proad,const struct player * pplayer,const struct tile * ptile)217 bool can_build_road_base(const struct road_type *proad,
218                          const struct player *pplayer,
219                          const struct tile *ptile)
220 {
221   if (!road_can_be_built(proad, ptile)) {
222     return FALSE;
223   }
224 
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);
232 
233       if (road_has_flag(old, RF_PREVENTS_OTHER_ROADS)
234           && tile_has_extra(ptile, poextra)) {
235         return FALSE;
236       }
237     } extra_type_by_cause_iterate_end;
238   }
239 
240   return TRUE;
241 }
242 
243 /****************************************************************************
244   Tells if player and optionally unit have road building requirements
245   fulfilled.
246 ****************************************************************************/
are_road_reqs_fulfilled(const struct road_type * proad,const struct player * pplayer,const struct unit * punit,const struct tile * ptile)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)
251 {
252   struct extra_type *pextra = road_extra_get(proad);
253   const struct unit_type *utype;
254 
255   if (punit == NULL) {
256     utype = NULL;
257   } else {
258     utype = unit_type_get(punit);
259   }
260 
261   if (requirement_vector_size(&proad->first_reqs) > 0) {
262     bool beginning = TRUE;
263 
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;
272           }
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;
279           }
280         } adjc_iterate_end;
281       }
282 
283       if (!beginning) {
284         break;
285       }
286     } extra_type_list_iterate_end;
287 
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;
293       }
294     }
295   }
296 
297   return are_reqs_active(pplayer, tile_owner(ptile), NULL, NULL, ptile,
298                          punit, utype, NULL, NULL, &pextra->reqs,
299                          RPT_POSSIBLE);
300 }
301 
302 /****************************************************************************
303   Tells if player can build road to tile with suitable unit.
304 ****************************************************************************/
player_can_build_road(const struct road_type * proad,const struct player * pplayer,const struct tile * ptile)305 bool player_can_build_road(const struct road_type *proad,
306                            const struct player *pplayer,
307                            const struct tile *ptile)
308 {
309   if (!can_build_road_base(proad, pplayer, ptile)) {
310     return FALSE;
311   }
312 
313   return are_road_reqs_fulfilled(proad, pplayer, NULL, ptile);
314 }
315 
316 /****************************************************************************
317   Tells if unit can build road on tile.
318 ****************************************************************************/
can_build_road(struct road_type * proad,const struct unit * punit,const struct tile * ptile)319 bool can_build_road(struct road_type *proad,
320 		    const struct unit *punit,
321 		    const struct tile *ptile)
322 {
323   struct player *pplayer = unit_owner(punit);
324 
325   if (!can_build_road_base(proad, pplayer, ptile)) {
326     return FALSE;
327   }
328 
329   return are_road_reqs_fulfilled(proad, pplayer, punit, ptile);
330 }
331 
332 /****************************************************************************
333   Count tiles with specified road near the tile. Can be called with NULL
334   road.
335 ****************************************************************************/
count_road_near_tile(const struct tile * ptile,const struct road_type * proad)336 int count_road_near_tile(const struct tile *ptile, const struct road_type *proad)
337 {
338   int count = 0;
339 
340   if (proad == NULL) {
341     return 0;
342   }
343 
344   adjc_iterate(ptile, adjc_tile) {
345     if (tile_has_road(adjc_tile, proad)) {
346       count++;
347     }
348   } adjc_iterate_end;
349 
350   return count;
351 }
352 
353 /****************************************************************************
354   Count tiles with any river near the tile.
355 ****************************************************************************/
count_river_near_tile(const struct tile * ptile,const struct extra_type * priver)356 int count_river_near_tile(const struct tile *ptile,
357                           const struct extra_type *priver)
358 {
359   int count = 0;
360 
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++;
368     }
369   } cardinal_adjc_iterate_end;
370 
371   return count;
372 }
373 
374 /****************************************************************************
375   Count tiles with river of specific type cardinally adjacent to the tile.
376 ****************************************************************************/
count_river_type_tile_card(const struct tile * ptile,const struct extra_type * priver,bool percentage)377 int count_river_type_tile_card(const struct tile *ptile,
378                                const struct extra_type *priver,
379                                bool percentage)
380 {
381   int count = 0;
382   int total = 0;
383 
384   fc_assert(priver != NULL);
385 
386   cardinal_adjc_iterate(ptile, adjc_tile) {
387     if (tile_has_extra(adjc_tile, priver)) {
388       count++;
389     }
390     total++;
391   } cardinal_adjc_iterate_end;
392 
393   if (percentage) {
394     count = count * 100 / total;
395   }
396   return count;
397 }
398 
399 /****************************************************************************
400   Count tiles with river of specific type near the tile.
401 ****************************************************************************/
count_river_type_near_tile(const struct tile * ptile,const struct extra_type * priver,bool percentage)402 int count_river_type_near_tile(const struct tile *ptile,
403                                const struct extra_type *priver,
404                                bool percentage)
405 {
406   int count = 0;
407   int total = 0;
408 
409   fc_assert(priver != NULL);
410 
411   adjc_iterate(ptile, adjc_tile) {
412     if (tile_has_extra(adjc_tile, priver)) {
413       count++;
414     }
415     total++;
416   } adjc_iterate_end;
417 
418   if (percentage) {
419     count = count * 100 / total;
420   }
421   return count;
422 }
423 
424 /****************************************************************************
425   Check if road provides effect
426 ****************************************************************************/
road_has_flag(const struct road_type * proad,enum road_flag_id flag)427 bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
428 {
429   return BV_ISSET(proad->flags, flag);
430 }
431 
432 /****************************************************************************
433   Returns TRUE iff any cardinally adjacent tile contains a road with
434   the given flag (does not check ptile itself).
435 ****************************************************************************/
is_road_flag_card_near(const struct tile * ptile,enum road_flag_id flag)436 bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
437 {
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;
443         }
444       } cardinal_adjc_iterate_end;
445     }
446   } extra_type_by_cause_iterate_end;
447 
448   return FALSE;
449 }
450 
451 /****************************************************************************
452   Returns TRUE iff any adjacent tile contains a road with the given flag
453   (does not check ptile itself).
454 ****************************************************************************/
is_road_flag_near_tile(const struct tile * ptile,enum road_flag_id flag)455 bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
456 {
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;
462         }
463       } adjc_iterate_end;
464     }
465   } extra_type_by_cause_iterate_end;
466 
467   return FALSE;
468 }
469 
470 /****************************************************************************
471   Is tile native to road?
472 ****************************************************************************/
is_native_tile_to_road(const struct road_type * proad,const struct tile * ptile)473 bool is_native_tile_to_road(const struct road_type *proad,
474                             const struct tile *ptile)
475 {
476   struct extra_type *pextra;
477 
478   if (road_has_flag(proad, RF_RIVER)) {
479     if (!terrain_has_flag(tile_terrain(ptile), TER_CAN_HAVE_RIVER)) {
480       return FALSE;
481     }
482   } else if (tile_terrain(ptile)->road_time == 0) {
483     return FALSE;
484   }
485 
486   pextra = road_extra_get(proad);
487 
488   return are_reqs_active(NULL, NULL, NULL, NULL, ptile,
489                          NULL, NULL, NULL, NULL,
490                          &pextra->reqs, RPT_POSSIBLE);
491 }
492 
493 /****************************************************************************
494   Is extra cardinal only road.
495 ****************************************************************************/
is_cardinal_only_road(const struct extra_type * pextra)496 bool is_cardinal_only_road(const struct extra_type *pextra)
497 {
498   const struct road_type *proad;
499 
500   if (!is_extra_caused_by(pextra, EC_ROAD)) {
501     return FALSE;
502   }
503 
504   proad = extra_road_get(pextra);
505 
506   return proad->move_mode == RMM_CARDINAL || proad->move_mode == RMM_RELAXED;
507 }
508 
509 /****************************************************************************
510   Does road type provide move bonus
511 ****************************************************************************/
road_provides_move_bonus(const struct road_type * proad)512 bool road_provides_move_bonus(const struct road_type *proad)
513 {
514   return proad->move_cost >= 0;
515 }
516