Freeciv21
Develop your civilization from humble roots to a global empire
road.cpp
Go to the documentation of this file.
1 /*
2 _ ._ Copyright (c) 1996-2021 Freeciv21 and Freeciv contributors.
3  \ | This file is part of Freeciv21. Freeciv21 is free software: you
4  \_| can redistribute it and/or modify it under the terms of the
5  .' '. GNU General Public License as published by the Free
6  :O O: Software Foundation, either version 3 of the License,
7  '/ \' or (at your option) any later version. You should have
8  :X: received a copy of the GNU General Public License along with
9  :X: Freeciv21. If not, see https://www.gnu.org/licenses/.
10  */
11 
12 // common
13 #include "extras.h"
14 #include "fc_types.h"
15 #include "game.h"
16 #include "map.h"
17 
18 #include "road.h"
19 
23 Road_type_id road_number(const struct road_type *proad)
24 {
25  fc_assert_ret_val(nullptr != proad, 0);
26 
27  return proad->id;
28 }
29 
33 struct extra_type *road_extra_get(const struct road_type *proad)
34 {
35  return proad->self;
36 }
37 
41 Road_type_id road_count() { return game.control.num_road_types; }
42 
47 {
48  struct extra_type_list *roads;
49 
51 
52  if (roads == nullptr || id < 0 || id >= extra_type_list_size(roads)) {
53  return nullptr;
54  }
55 
56  return extra_road_get(extra_type_list_get(roads, id));
57 }
58 
63 int compare_road_move_cost(const struct extra_type *const *p,
64  const struct extra_type *const *q)
65 {
66  const struct road_type *proad = extra_road_get(*p);
67  const struct road_type *qroad = extra_road_get(*q);
68 
69  if (proad->move_cost > qroad->move_cost) {
70  return -1; // q is faster
71  } else if (proad->move_cost == qroad->move_cost) {
72  return 0;
73  } else {
74  return 1; // p is faster
75  }
76 }
77 
81 void road_type_init(struct extra_type *pextra, int idx)
82 {
83  auto *proad = new road_type;
84 
85  pextra->data.road = proad;
86 
87  requirement_vector_init(&proad->first_reqs);
88 
89  proad->id = idx;
90  proad->integrators = nullptr;
91  proad->self = pextra;
92 }
93 
98 {
99  extra_type_by_cause_iterate(EC_ROAD, pextra)
100  {
101  struct road_type *proad = extra_road_get(pextra);
102 
103  proad->integrators = extra_type_list_new();
104  // Roads always integrate with themselves.
105  extra_type_list_append(proad->integrators, pextra);
106  extra_type_by_cause_iterate(EC_ROAD, oextra)
107  {
108  struct road_type *oroad = extra_road_get(oextra);
109 
110  if (BV_ISSET(proad->integrates, road_number(oroad))) {
111  extra_type_list_append(proad->integrators, oextra);
112  }
113  }
115  extra_type_list_unique(proad->integrators);
116  extra_type_list_sort(proad->integrators, &compare_road_move_cost);
117  }
119 }
120 
125 {
126  extra_type_by_cause_iterate(EC_ROAD, pextra)
127  {
128  struct road_type *proad = extra_road_get(pextra);
129 
130  requirement_vector_free(&proad->first_reqs);
131 
132  if (proad->integrators != nullptr) {
133  extra_type_list_destroy(proad->integrators);
134  proad->integrators = nullptr;
135  }
136  }
138 }
139 
143 enum road_compat road_compat_special(const struct road_type *proad)
144 {
145  return proad->compat;
146 }
147 
153 {
154  if (compat == ROCO_NONE) {
155  return nullptr;
156  }
157 
158  extra_type_by_cause_iterate(EC_ROAD, pextra)
159  {
160  struct road_type *proad = extra_road_get(pextra);
161  if (road_compat_special(proad) == compat) {
162  return proad;
163  }
164  }
166 
167  return nullptr;
168 }
169 
173 bool road_can_be_built(const struct road_type *proad,
174  const struct tile *ptile)
175 {
176  if (!(road_extra_get(proad)->buildable)) {
177  // Road type not buildable.
178  return false;
179  }
180 
181  if (tile_has_road(ptile, proad)) {
182  // Road exist already
183  return false;
184  }
185 
186  if (tile_terrain(ptile)->road_time == 0) {
187  return false;
188  }
189 
190  return true;
191 }
192 
197 static bool are_road_reqs_fulfilled(const struct road_type *proad,
198  const struct player *pplayer,
199  const struct unit *punit,
200  const struct tile *ptile)
201 {
202  struct extra_type *pextra = road_extra_get(proad);
203  const struct unit_type *utype;
204 
205  if (punit == nullptr) {
206  utype = nullptr;
207  } else {
208  utype = unit_type_get(punit);
209  }
210 
211  if (requirement_vector_size(&proad->first_reqs) > 0) {
212  bool beginning = true;
213 
214  extra_type_list_iterate(proad->integrators, iroad)
215  {
216  /* FIXME: mixing cardinal and non-cardinal roads as integrators is
217  * probably not a good idea. */
218  if (is_cardinal_only_road(iroad)) {
219  cardinal_adjc_iterate(&(wld.map), ptile, adjc_tile)
220  {
221  if (tile_has_extra(adjc_tile, iroad)) {
222  beginning = false;
223  break;
224  }
225  }
227  } else {
228  adjc_iterate(&(wld.map), ptile, adjc_tile)
229  {
230  if (tile_has_extra(adjc_tile, iroad)) {
231  beginning = false;
232  break;
233  }
234  }
236  }
237 
238  if (!beginning) {
239  break;
240  }
241  }
243 
244  if (beginning) {
245  if (!are_reqs_active(pplayer, tile_owner(ptile), nullptr, nullptr,
246  ptile, punit, utype, nullptr, nullptr, nullptr,
247  &proad->first_reqs, RPT_POSSIBLE)) {
248  return false;
249  }
250  }
251  }
252 
253  return are_reqs_active(pplayer, tile_owner(ptile), nullptr, nullptr, ptile,
254  punit, utype, nullptr, nullptr, nullptr,
255  &pextra->reqs, RPT_POSSIBLE);
256 }
257 
261 bool player_can_build_road(const struct road_type *proad,
262  const struct player *pplayer,
263  const struct tile *ptile)
264 {
265  if (!can_build_extra_base(road_extra_get(proad), pplayer, ptile)) {
266  return false;
267  }
268 
269  return are_road_reqs_fulfilled(proad, pplayer, nullptr, ptile);
270 }
271 
275 bool can_build_road(struct road_type *proad, const struct unit *punit,
276  const struct tile *ptile)
277 {
278  struct player *pplayer = unit_owner(punit);
279 
280  if (!can_build_extra_base(road_extra_get(proad), pplayer, ptile)) {
281  return false;
282  }
283 
284  return are_road_reqs_fulfilled(proad, pplayer, punit, ptile);
285 }
286 
290 int count_river_near_tile(const struct tile *ptile,
291  const struct extra_type *priver)
292 {
293  int count = 0;
294 
295  cardinal_adjc_iterate(&(wld.map), ptile, adjc_tile)
296  {
297  if (priver == nullptr && tile_has_river(adjc_tile)) {
298  // Some river
299  count++;
300  } else if (priver != nullptr && tile_has_extra(adjc_tile, priver)) {
301  // Specific river
302  count++;
303  }
304  }
306 
307  return count;
308 }
309 
313 int count_river_type_tile_card(const struct tile *ptile,
314  const struct extra_type *priver,
315  bool percentage)
316 {
317  int count = 0;
318  int total = 0;
319 
320  fc_assert(priver != nullptr);
321 
322  cardinal_adjc_iterate(&(wld.map), ptile, adjc_tile)
323  {
324  if (tile_has_extra(adjc_tile, priver)) {
325  count++;
326  }
327  total++;
328  }
330 
331  if (percentage) {
332  count = count * 100 / std::max(total, 1);
333  }
334  return count;
335 }
336 
340 int count_river_type_near_tile(const struct tile *ptile,
341  const struct extra_type *priver,
342  bool percentage)
343 {
344  int count = 0;
345  int total = 0;
346 
347  fc_assert(priver != nullptr);
348 
349  adjc_iterate(&(wld.map), ptile, adjc_tile)
350  {
351  if (tile_has_extra(adjc_tile, priver)) {
352  count++;
353  }
354  total++;
355  }
357 
358  if (percentage) {
359  count = count * 100 / std::max(1, total);
360  }
361  return count;
362 }
363 
367 bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
368 {
369  return BV_ISSET(proad->flags, flag);
370 }
371 
376 bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
377 {
378  extra_type_by_cause_iterate(EC_ROAD, pextra)
379  {
380  if (road_has_flag(extra_road_get(pextra), flag)) {
381  cardinal_adjc_iterate(&(wld.map), ptile, adjc_tile)
382  {
383  if (tile_has_extra(adjc_tile, pextra)) {
384  return true;
385  }
386  }
388  }
389  }
391 
392  return false;
393 }
394 
399 bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
400 {
401  extra_type_by_cause_iterate(EC_ROAD, pextra)
402  {
403  if (road_has_flag(extra_road_get(pextra), flag)) {
404  adjc_iterate(&(wld.map), ptile, adjc_tile)
405  {
406  if (tile_has_extra(adjc_tile, pextra)) {
407  return true;
408  }
409  }
411  }
412  }
414 
415  return false;
416 }
417 
421 bool is_cardinal_only_road(const struct extra_type *pextra)
422 {
423  const struct road_type *proad;
424 
425  if (!is_extra_caused_by(pextra, EC_ROAD)) {
426  return false;
427  }
428 
429  proad = extra_road_get(pextra);
430 
431  return proad->move_mode == RMM_CARDINAL || proad->move_mode == RMM_RELAXED;
432 }
433 
437 bool road_provides_move_bonus(const struct road_type *proad)
438 {
439  return proad->move_cost >= 0;
440 }
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
char * roads
Definition: comments.cpp:36
bool can_build_extra_base(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Tells if player can build extra to tile with suitable unit.
Definition: extras.cpp:371
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Returns extra type for given cause.
Definition: extras.cpp:224
#define extra_type_list_iterate(extralist, pextra)
Definition: extras.h:145
#define is_extra_caused_by(e, c)
Definition: extras.h:182
#define extra_type_list_iterate_end
Definition: extras.h:147
#define extra_road_get(_e_)
Definition: extras.h:171
#define extra_type_by_cause_iterate_end
Definition: extras.h:307
#define extra_type_by_cause_iterate(_cause, _extra)
Definition: extras.h:299
int Road_type_id
Definition: fc_types.h:301
road_compat
Definition: fc_types.h:1067
@ ROCO_NONE
Definition: fc_types.h:1067
@ RPT_POSSIBLE
Definition: fc_types.h:567
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define adjc_iterate_end
Definition: map.h:358
#define cardinal_adjc_iterate_end
Definition: map.h:384
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:351
#define cardinal_adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:380
bool are_reqs_active(const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, const struct requirement_vector *reqs, const enum req_problem_type prob_type, const enum vision_layer vision_layer, const enum national_intelligence nintel)
Checks the requirement(s) to see if they are active on the given target.
Road_type_id road_number(const struct road_type *proad)
Return the road id.
Definition: road.cpp:23
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Check if road provides effect.
Definition: road.cpp:367
bool is_road_flag_card_near(const struct tile *ptile, enum road_flag_id flag)
Returns TRUE iff any cardinally adjacent tile contains a road with the given flag (does not check pti...
Definition: road.cpp:376
bool is_cardinal_only_road(const struct extra_type *pextra)
Is extra cardinal only road.
Definition: road.cpp:421
bool is_road_flag_near_tile(const struct tile *ptile, enum road_flag_id flag)
Returns TRUE iff any adjacent tile contains a road with the given flag (does not check ptile itself).
Definition: road.cpp:399
enum road_compat road_compat_special(const struct road_type *proad)
Return tile special that used to represent this road type.
Definition: road.cpp:143
static bool are_road_reqs_fulfilled(const struct road_type *proad, const struct player *pplayer, const struct unit *punit, const struct tile *ptile)
Tells if player and optionally unit have road building requirements fulfilled.
Definition: road.cpp:197
int count_river_near_tile(const struct tile *ptile, const struct extra_type *priver)
Count tiles with any river near the tile.
Definition: road.cpp:290
int count_river_type_near_tile(const struct tile *ptile, const struct extra_type *priver, bool percentage)
Count tiles with river of specific type near the tile.
Definition: road.cpp:340
bool road_provides_move_bonus(const struct road_type *proad)
Does road type provide move bonus.
Definition: road.cpp:437
bool player_can_build_road(const struct road_type *proad, const struct player *pplayer, const struct tile *ptile)
Tells if player can build road to tile with suitable unit.
Definition: road.cpp:261
struct road_type * road_by_compat_special(enum road_compat compat)
Return road type represented by given compatibility special, or nullptr if special does not represent...
Definition: road.cpp:152
void road_integrators_cache_init()
Initialize the road integrators cache.
Definition: road.cpp:97
int count_river_type_tile_card(const struct tile *ptile, const struct extra_type *priver, bool percentage)
Count tiles with river of specific type cardinally adjacent to the tile.
Definition: road.cpp:313
Road_type_id road_count()
Return the number of road_types.
Definition: road.cpp:41
void road_type_init(struct extra_type *pextra, int idx)
Initialize road_type structures.
Definition: road.cpp:81
int compare_road_move_cost(const struct extra_type *const *p, const struct extra_type *const *q)
This function is passed to road_type_list_sort() to sort a list of roads in ascending move_cost (fast...
Definition: road.cpp:63
void road_types_free()
Free the memory associated with road types.
Definition: road.cpp:124
bool road_can_be_built(const struct road_type *proad, const struct tile *ptile)
Tells if road can build to tile if all other requirements are met.
Definition: road.cpp:173
struct road_type * road_by_number(Road_type_id id)
Return road type of given id.
Definition: road.cpp:46
struct extra_type * road_extra_get(const struct road_type *proad)
Return extra that road is.
Definition: road.cpp:33
bool can_build_road(struct road_type *proad, const struct unit *punit, const struct tile *ptile)
Tells if unit can build road on tile.
Definition: road.cpp:275
static struct compatibility compat[]
Definition: savecompat.cpp:109
struct packet_ruleset_control control
Definition: game.h:74
struct road_type * road
Definition: extras.h:135
struct extra_type::@22 data
struct requirement_vector reqs
Definition: extras.h:90
Definition: player.h:231
Definition: road.h:54
struct extra_type * self
Definition: road.h:74
struct requirement_vector first_reqs
Definition: road.h:64
enum road_move_mode move_mode
Definition: road.h:58
int id
Definition: road.h:55
struct extra_type_list * integrators
Definition: road.h:72
bv_roads integrates
Definition: road.h:66
bv_road_flags flags
Definition: road.h:67
int move_cost
Definition: road.h:57
enum road_compat compat
Definition: road.h:62
Definition: tile.h:42
Definition: unit.h:134
struct civ_map map
Definition: world_object.h:21
bool tile_has_river(const struct tile *ptile)
Tile has any river type.
Definition: tile.cpp:876
bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
Returns TRUE if the given tile has a road of given type on it.
Definition: tile.cpp:868
#define tile_terrain(_tile)
Definition: tile.h:93
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
#define tile_owner(_tile)
Definition: tile.h:78
#define unit_owner(_pu)
Definition: unit.h:370
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114