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>
30 #include "traderoutes.h"
32 const char *trade_route_type_names
[] = {
33 "National", "NationalIC", "IN", "INIC", "Ally", "AllyIC",
34 "Enemy", "EnemyIC", "Team", "TeamIC"
37 const char *traderoute_cancelling_type_names
[] = {
38 "Active", "Inactive", "Cancel"
41 struct trade_route_settings trtss
[TRT_LAST
];
43 static struct goods_type goods
[MAX_GOODS_TYPES
];
45 /*************************************************************************
46 Return current maximum number of trade routes city can have.
47 *************************************************************************/
48 int max_trade_routes(const struct city
*pcity
)
50 int eft
= get_city_bonus(pcity
, EFT_MAX_TRADE_ROUTES
);
52 return CLIP(0, eft
, MAX_TRADE_ROUTES
);
55 /*************************************************************************
56 What is type of the traderoute between two cities.
57 *************************************************************************/
58 enum trade_route_type
cities_trade_route_type(const struct city
*pcity1
,
59 const struct city
*pcity2
)
61 struct player
*plr1
= city_owner(pcity1
);
62 struct player
*plr2
= city_owner(pcity2
);
65 struct player_diplstate
*ds
= player_diplstate_get(plr1
, plr2
);
67 if (city_tile(pcity1
)->continent
!= city_tile(pcity2
)->continent
) {
81 fc_assert(ds
->type
!= DS_LAST
);
101 fc_assert(ds
->type
!= DS_LAST
);
109 if (city_tile(pcity1
)->continent
!= city_tile(pcity2
)->continent
) {
110 return TRT_NATIONAL_IC
;
119 /*************************************************************************
120 Return percentage bonus for trade route type.
121 *************************************************************************/
122 int trade_route_type_trade_pct(enum trade_route_type type
)
124 if (type
< 0 || type
>= TRT_LAST
) {
128 return trtss
[type
].trade_pct
;
131 /*************************************************************************
132 Initialize trade route types.
133 *************************************************************************/
134 void trade_route_types_init(void)
136 enum trade_route_type type
;
138 for (type
= TRT_NATIONAL
; type
< TRT_LAST
; type
++) {
139 struct trade_route_settings
*set
= trade_route_settings_by_type(type
);
141 set
->trade_pct
= 100;
145 /*************************************************************************
146 Return human readable name of trade route type
147 *************************************************************************/
148 const char *trade_route_type_name(enum trade_route_type type
)
150 fc_assert_ret_val(type
>= TRT_NATIONAL
&& type
< TRT_LAST
, NULL
);
152 return trade_route_type_names
[type
];
155 /*************************************************************************
156 Get trade route type by name.
157 *************************************************************************/
158 enum trade_route_type
trade_route_type_by_name(const char *name
)
160 enum trade_route_type type
;
162 for (type
= TRT_NATIONAL
; type
< TRT_LAST
; type
++) {
163 if (!fc_strcasecmp(trade_route_type_names
[type
], name
)) {
171 /*************************************************************************
172 Return human readable name of traderoute cancelling type
173 *************************************************************************/
174 const char *traderoute_cancelling_type_name(enum traderoute_illegal_cancelling type
)
176 fc_assert_ret_val(type
>= TRI_ACTIVE
&& type
< TRI_LAST
, NULL
);
178 return traderoute_cancelling_type_names
[type
];
181 /*************************************************************************
182 Get traderoute cancelling type by name.
183 *************************************************************************/
184 enum traderoute_illegal_cancelling
traderoute_cancelling_type_by_name(const char *name
)
186 enum traderoute_illegal_cancelling type
;
188 for (type
= TRI_ACTIVE
; type
< TRI_LAST
; type
++) {
189 if (!fc_strcasecmp(traderoute_cancelling_type_names
[type
], name
)) {
197 /*************************************************************************
198 Get trade route settings related to type.
199 *************************************************************************/
200 struct trade_route_settings
*
201 trade_route_settings_by_type(enum trade_route_type type
)
203 fc_assert_ret_val(type
>= TRT_NATIONAL
&& type
< TRT_LAST
, NULL
);
208 /**************************************************************************
209 Return TRUE iff the two cities are capable of trade; i.e., if a caravan
210 from one city can enter the other to sell its goods.
212 See also can_establish_trade_route().
213 **************************************************************************/
214 bool can_cities_trade(const struct city
*pc1
, const struct city
*pc2
)
216 /* If you change the logic here, make sure to update the help in
217 * helptext_unit(). */
218 return (pc1
&& pc2
&& pc1
!= pc2
219 && (city_owner(pc1
) != city_owner(pc2
)
220 || map_distance(pc1
->tile
, pc2
->tile
)
221 >= game
.info
.trademindist
)
222 && (trade_route_type_trade_pct(cities_trade_route_type(pc1
, pc2
))
226 /****************************************************************************
227 Return the minimum value of the sum of trade routes which could be
228 replaced by a new one. The target routes to be removed
229 will be put into 'would_remove', if set.
230 ****************************************************************************/
231 int city_trade_removable(const struct city
*pcity
,
232 struct trade_route_list
*would_remove
)
234 struct trade_route
*sorted
[MAX_TRADE_ROUTES
];
237 /* Sort trade route values. */
239 trade_routes_iterate(pcity
, proute
) {
240 for (j
= num
; j
> 0 && (proute
->value
< sorted
[j
- 1]->value
) ; j
--) {
241 sorted
[j
] = sorted
[j
- 1];
245 } trade_routes_iterate_end
;
247 /* No trade routes at all. */
252 /* Adjust number of concerned trade routes. */
253 num
+= 1 - max_trade_routes(pcity
);
259 for (i
= j
= 0; i
< num
; i
++) {
260 j
+= sorted
[i
]->value
;
261 if (NULL
!= would_remove
) {
262 trade_route_list_append(would_remove
, sorted
[i
]);
269 /**************************************************************************
270 Returns TRUE iff the two cities can establish a trade route. We look
271 at the distance and ownership of the cities as well as their existing
272 trade routes. Should only be called if you already know that
274 **************************************************************************/
275 bool can_establish_trade_route(const struct city
*pc1
, const struct city
*pc2
)
281 if (!pc1
|| !pc2
|| pc1
== pc2
282 || !can_cities_trade(pc1
, pc2
)
283 || have_cities_trade_route(pc1
, pc2
)) {
287 /* First check if cities can have trade routes at all. */
288 maxpc1
= max_trade_routes(pc1
);
292 maxpc2
= max_trade_routes(pc2
);
297 if (city_num_trade_routes(pc1
) >= maxpc1
) {
298 trade
= trade_base_between_cities(pc1
, pc2
);
299 /* can we replace trade route? */
300 if (city_trade_removable(pc1
, NULL
) >= trade
) {
305 if (city_num_trade_routes(pc2
) >= maxpc2
) {
307 trade
= trade_base_between_cities(pc1
, pc2
);
309 /* can we replace trade route? */
310 if (city_trade_removable(pc2
, NULL
) >= trade
) {
318 /**************************************************************************
319 Return the trade that exists between these cities, assuming they have a
321 **************************************************************************/
322 int trade_base_between_cities(const struct city
*pc1
, const struct city
*pc2
)
326 if (NULL
!= pc1
&& NULL
!= pc1
->tile
327 && NULL
!= pc2
&& NULL
!= pc2
->tile
) {
328 int real_dist
= real_map_distance(pc1
->tile
, pc2
->tile
);
329 int weighted_distance
330 = ((100 - game
.info
.trade_world_rel_pct
) * real_dist
331 + game
.info
.trade_world_rel_pct
* (real_dist
* 40 / MAX(wld
.map
.xsize
, wld
.map
.ysize
))) / 100;
333 bonus
= weighted_distance
334 + city_size_get(pc1
) + city_size_get(pc2
);
336 bonus
= bonus
* trade_route_type_trade_pct(cities_trade_route_type(pc1
, pc2
)) / 100;
344 /**************************************************************************
345 Get trade income specific to route's good.
346 **************************************************************************/
347 int trade_from_route(const struct city
*pc1
, const struct trade_route
*route
,
350 if (route
->dir
== RDIR_TO
) {
351 return base
* route
->goods
->to_pct
/ 100;
354 return base
* route
->goods
->from_pct
/ 100;
357 /**************************************************************************
358 Return number of trade route city has
359 **************************************************************************/
360 int city_num_trade_routes(const struct city
*pcity
)
362 return trade_route_list_size(pcity
->routes
);
365 /**************************************************************************
366 Returns the revenue trade bonus - you get this when establishing a
367 trade route and also when you simply sell your trade goods at the
370 If you change this calculation remember to also update its duplication
371 in dai_choose_trade_route()
372 **************************************************************************/
373 int get_caravan_enter_city_trade_bonus(const struct city
*pc1
,
374 const struct city
*pc2
,
375 const bool establish_trade
)
379 /* Should this be real_map_distance? */
380 tb
= map_distance(pc1
->tile
, pc2
->tile
) + 10;
381 tb
= (tb
* (pc1
->surplus
[O_TRADE
] + pc2
->surplus
[O_TRADE
])) / 24;
383 /* Trade_revenue_bonus increases revenue by power of 2 in milimes */
384 bonus
= get_target_bonus_effects(NULL
,
385 city_owner(pc1
), city_owner(pc2
),
386 pc1
, NULL
, city_tile(pc1
),
387 /* TODO: Should unit requirements be
388 * allowed so stuff like moves left and
389 * unit type can modify the bonus? */
392 /* Could be used to reduce the one time
393 * bonus if no trade route is
395 action_by_number(establish_trade
?
398 EFT_TRADE_REVENUE_BONUS
);
400 /* Be mercy full to players with small amounts. Round up. */
401 tb
= ceil((float)tb
* pow(2.0, (double)bonus
/ 1000.0));
406 /**************************************************************************
407 Check if cities have an established trade route.
408 **************************************************************************/
409 bool have_cities_trade_route(const struct city
*pc1
, const struct city
*pc2
)
411 trade_partners_iterate(pc1
, route_to
) {
412 if (route_to
->id
== pc2
->id
) {
415 } trade_partners_iterate_end
;
420 /****************************************************************************
421 Initialize goods structures.
422 ****************************************************************************/
423 void goods_init(void)
427 for (i
= 0; i
< MAX_GOODS_TYPES
; i
++) {
430 requirement_vector_init(&(goods
[i
].reqs
));
431 goods
[i
].disabled
= FALSE
;
432 goods
[i
].helptext
= NULL
;
436 /****************************************************************************
437 Free the memory associated with goods
438 ****************************************************************************/
439 void goods_free(void)
443 for (i
= 0; i
< MAX_GOODS_TYPES
; i
++) {
444 requirement_vector_free(&(goods
[i
].reqs
));
446 if (NULL
!= goods
[i
].helptext
) {
447 strvec_destroy(goods
[i
].helptext
);
448 goods
[i
].helptext
= NULL
;
453 /**************************************************************************
455 **************************************************************************/
456 Goods_type_id
goods_number(const struct goods_type
*pgood
)
458 fc_assert_ret_val(NULL
!= pgood
, -1);
463 /**************************************************************************
464 Return the goods index.
466 Currently same as goods_number(), paired with goods_count()
467 indicates use as an array index.
468 **************************************************************************/
469 Goods_type_id
goods_index(const struct goods_type
*pgood
)
471 fc_assert_ret_val(NULL
!= pgood
, -1);
473 return pgood
- goods
;
476 /****************************************************************************
477 Return goods type of given id.
478 ****************************************************************************/
479 struct goods_type
*goods_by_number(Goods_type_id id
)
481 fc_assert_ret_val(id
>= 0 && id
< game
.control
.num_goods_types
, NULL
);
486 /****************************************************************************
487 Return translated name of this goods type.
488 ****************************************************************************/
489 const char *goods_name_translation(struct goods_type
*pgood
)
491 return name_translation_get(&pgood
->name
);
494 /****************************************************************************
495 Return untranslated name of this goods type.
496 ****************************************************************************/
497 const char *goods_rule_name(struct goods_type
*pgood
)
499 return rule_name_get(&pgood
->name
);
502 /**************************************************************************
503 Returns goods type matching rule name or NULL if there is no goods type
505 **************************************************************************/
506 struct goods_type
*goods_by_rule_name(const char *name
)
516 goods_type_iterate(pgood
) {
517 if (!fc_strcasecmp(goods_rule_name(pgood
), qs
)) {
520 } goods_type_iterate_end
;
525 /**************************************************************************
526 Returns goods type matching the translated name, or NULL if there is no
527 goods type with that name.
528 **************************************************************************/
529 struct goods_type
*goods_by_translated_name(const char *name
)
531 goods_type_iterate(pgood
) {
532 if (0 == strcmp(goods_name_translation(pgood
), name
)) {
535 } goods_type_iterate_end
;
540 /****************************************************************************
541 Check if goods has given flag
542 ****************************************************************************/
543 bool goods_has_flag(const struct goods_type
*pgood
, enum goods_flag_id flag
)
545 return BV_ISSET(pgood
->flags
, flag
);
548 /****************************************************************************
549 Can the city provide goods.
550 ****************************************************************************/
551 bool goods_can_be_provided(struct city
*pcity
, struct goods_type
*pgood
,
554 struct unit_type
*ptype
;
557 ptype
= unit_type_get(punit
);
562 return are_reqs_active(city_owner(pcity
), NULL
,
563 pcity
, NULL
, city_tile(pcity
),
564 punit
, ptype
, NULL
, NULL
, NULL
,
565 &pgood
->reqs
, RPT_CERTAIN
);
568 /****************************************************************************
569 Does city receive goods
570 ****************************************************************************/
571 bool city_receives_goods(const struct city
*pcity
,
572 const struct goods_type
*pgood
)
574 trade_routes_iterate(pcity
, proute
) {
575 if (proute
->goods
== pgood
576 && (proute
->dir
== RDIR_TO
|| proute
->dir
== RDIR_BIDIRECTIONAL
)) {
579 } trade_routes_iterate_end
;
584 /****************************************************************************
585 Return goods type for the new traderoute between given cities.
586 ****************************************************************************/
587 struct goods_type
*goods_from_city_to_unit(struct city
*src
, struct unit
*punit
)
590 struct goods_type
*potential
[MAX_GOODS_TYPES
];
592 goods_type_iterate(pgood
) {
593 if (goods_can_be_provided(src
, pgood
, punit
)) {
594 potential
[i
++] = pgood
;
596 } goods_type_iterate_end
;
602 return potential
[fc_rand(i
)];