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>
28 #include "traderoutes.h"
30 const char *trade_route_type_names
[] = {
31 "National", "NationalIC", "IN", "INIC", "Ally", "AllyIC",
32 "Enemy", "EnemyIC", "Team", "TeamIC"
35 const char *traderoute_cancelling_type_names
[] = {
36 "Active", "Inactive", "Cancel"
39 struct trade_route_settings trtss
[TRT_LAST
];
41 /*************************************************************************
42 Return current maximum number of trade routes city can have.
43 *************************************************************************/
44 int max_trade_routes(const struct city
*pcity
)
46 int eft
= get_city_bonus(pcity
, EFT_MAX_TRADE_ROUTES
);
48 return CLIP(0, eft
, MAX_TRADE_ROUTES
);
51 /*************************************************************************
52 What is type of the traderoute between two cities.
53 *************************************************************************/
54 enum trade_route_type
cities_trade_route_type(const struct city
*pcity1
,
55 const struct city
*pcity2
)
57 struct player
*plr1
= city_owner(pcity1
);
58 struct player
*plr2
= city_owner(pcity2
);
61 struct player_diplstate
*ds
= player_diplstate_get(plr1
, plr2
);
63 if (city_tile(pcity1
)->continent
!= city_tile(pcity2
)->continent
) {
77 fc_assert(ds
->type
!= DS_LAST
);
97 fc_assert(ds
->type
!= DS_LAST
);
105 if (city_tile(pcity1
)->continent
!= city_tile(pcity2
)->continent
) {
106 return TRT_NATIONAL_IC
;
115 /*************************************************************************
116 Return percentage bonus for trade route type.
117 *************************************************************************/
118 int trade_route_type_trade_pct(enum trade_route_type type
)
120 if (type
< 0 || type
>= TRT_LAST
) {
124 return trtss
[type
].trade_pct
;
127 /*************************************************************************
128 Initialize trade route types.
129 *************************************************************************/
130 void trade_route_types_init(void)
132 enum trade_route_type type
;
134 for (type
= TRT_NATIONAL
; type
< TRT_LAST
; type
++) {
135 struct trade_route_settings
*set
= trade_route_settings_by_type(type
);
137 set
->trade_pct
= 100;
141 /*************************************************************************
142 Return human readable name of trade route type
143 *************************************************************************/
144 const char *trade_route_type_name(enum trade_route_type type
)
146 fc_assert_ret_val(type
>= TRT_NATIONAL
&& type
< TRT_LAST
, NULL
);
148 return trade_route_type_names
[type
];
151 /*************************************************************************
152 Get trade route type by name.
153 *************************************************************************/
154 enum trade_route_type
trade_route_type_by_name(const char *name
)
156 enum trade_route_type type
;
158 for (type
= TRT_NATIONAL
; type
< TRT_LAST
; type
++) {
159 if (!fc_strcasecmp(trade_route_type_names
[type
], name
)) {
167 /*************************************************************************
168 Return human readable name of traderoute cancelling type
169 *************************************************************************/
170 const char *traderoute_cancelling_type_name(enum traderoute_illegal_cancelling type
)
172 fc_assert_ret_val(type
>= TRI_ACTIVE
&& type
< TRI_LAST
, NULL
);
174 return traderoute_cancelling_type_names
[type
];
177 /*************************************************************************
178 Get traderoute cancelling type by name.
179 *************************************************************************/
180 enum traderoute_illegal_cancelling
traderoute_cancelling_type_by_name(const char *name
)
182 enum traderoute_illegal_cancelling type
;
184 for (type
= TRI_ACTIVE
; type
< TRI_LAST
; type
++) {
185 if (!fc_strcasecmp(traderoute_cancelling_type_names
[type
], name
)) {
193 /*************************************************************************
194 Get trade route settings related to type.
195 *************************************************************************/
196 struct trade_route_settings
*
197 trade_route_settings_by_type(enum trade_route_type type
)
199 fc_assert_ret_val(type
>= TRT_NATIONAL
&& type
< TRT_LAST
, NULL
);
204 /**************************************************************************
205 Return TRUE iff the two cities are capable of trade; i.e., if a caravan
206 from one city can enter the other to sell its goods.
208 See also can_establish_trade_route().
209 **************************************************************************/
210 bool can_cities_trade(const struct city
*pc1
, const struct city
*pc2
)
212 /* If you change the logic here, make sure to update the help in
213 * helptext_unit(). */
214 return (pc1
&& pc2
&& pc1
!= pc2
215 && (city_owner(pc1
) != city_owner(pc2
)
216 || map_distance(pc1
->tile
, pc2
->tile
)
217 >= game
.info
.trademindist
)
218 && (trade_route_type_trade_pct(cities_trade_route_type(pc1
, pc2
))
222 /****************************************************************************
223 Return the minimum value of the sum of trade routes which could be
224 replaced by a new one. The target cities of the concerned trade routes
225 are will be put into 'would_remove', if set.
226 ****************************************************************************/
227 int city_trade_removable(const struct city
*pcity
,
228 struct city_list
*would_remove
)
230 int sorted
[MAX_TRADE_ROUTES
];
233 FC_STATIC_ASSERT(ARRAY_SIZE(sorted
) == ARRAY_SIZE(pcity
->trade
),
234 incompatible_trade_array_size
);
235 FC_STATIC_ASSERT(ARRAY_SIZE(sorted
) == ARRAY_SIZE(pcity
->trade_value
),
236 incompatible_trade_value_array_size
);
238 /* Sort trade route values. */
240 for (i
= 0; i
< MAX_TRADE_ROUTES
; i
++) {
241 if (0 == pcity
->trade
[i
]) {
244 for (j
= num
; j
> 0 && (pcity
->trade_value
[i
]
245 < pcity
->trade_value
[sorted
[j
- 1]]); j
--) {
246 sorted
[j
] = sorted
[j
- 1];
252 /* No trade routes at all. */
257 /* Adjust number of concerned trade routes. */
258 num
+= 1 - max_trade_routes(pcity
);
264 for (i
= j
= 0; i
< num
; i
++) {
265 j
+= pcity
->trade_value
[sorted
[i
]];
266 if (NULL
!= would_remove
) {
267 struct city
*pother
= game_city_by_number(pcity
->trade
[sorted
[i
]]);
269 fc_assert(NULL
!= pother
);
270 city_list_append(would_remove
, pother
);
276 /**************************************************************************
277 Returns TRUE iff the two cities can establish a trade route. We look
278 at the distance and ownership of the cities as well as their existing
279 trade routes. Should only be called if you already know that
281 **************************************************************************/
282 bool can_establish_trade_route(const struct city
*pc1
, const struct city
*pc2
)
288 if (!pc1
|| !pc2
|| pc1
== pc2
289 || !can_cities_trade(pc1
, pc2
)
290 || have_cities_trade_route(pc1
, pc2
)) {
294 /* First check if cities can have trade routes at all. */
295 maxpc1
= max_trade_routes(pc1
);
299 maxpc2
= max_trade_routes(pc2
);
304 if (city_num_trade_routes(pc1
) >= maxpc1
) {
305 trade
= trade_between_cities(pc1
, pc2
);
306 /* can we replace trade route? */
307 if (city_trade_removable(pc1
, NULL
) >= trade
) {
312 if (city_num_trade_routes(pc2
) >= maxpc2
) {
314 trade
= trade_between_cities(pc1
, pc2
);
316 /* can we replace trade route? */
317 if (city_trade_removable(pc2
, NULL
) >= trade
) {
325 /**************************************************************************
326 Return the trade that exists between these cities, assuming they have a
328 **************************************************************************/
329 int trade_between_cities(const struct city
*pc1
, const struct city
*pc2
)
333 if (NULL
!= pc1
&& NULL
!= pc1
->tile
334 && NULL
!= pc2
&& NULL
!= pc2
->tile
) {
336 bonus
= real_map_distance(pc1
->tile
, pc2
->tile
)
337 + city_size_get(pc1
) + city_size_get(pc2
);
339 bonus
= bonus
* trade_route_type_trade_pct(cities_trade_route_type(pc1
, pc2
)) / 100;
347 /**************************************************************************
348 Return number of trade route city has
349 **************************************************************************/
350 int city_num_trade_routes(const struct city
*pcity
)
354 for (i
= 0; i
< MAX_TRADE_ROUTES
; i
++) {
355 if (pcity
->trade
[i
] != 0) {
363 /**************************************************************************
364 Returns the revenue trade bonus - you get this when establishing a
365 trade route and also when you simply sell your trade goods at the
368 If you change this calculation remember to also update its duplication
369 in dai_choose_trade_route()
370 **************************************************************************/
371 int get_caravan_enter_city_trade_bonus(const struct city
*pc1
,
372 const struct city
*pc2
,
373 const bool establish_trade
)
377 /* Should this be real_map_distance? */
378 tb
= map_distance(pc1
->tile
, pc2
->tile
) + 10;
379 tb
= (tb
* (pc1
->surplus
[O_TRADE
] + pc2
->surplus
[O_TRADE
])) / 24;
381 /* fudge factor to more closely approximate Civ2 behavior (Civ2 is
382 * really very different -- this just fakes it a little better) */
385 /* Trade_revenue_bonus increases revenue by power of 2 in milimes */
386 bonus
= get_city_bonus(pc1
, EFT_TRADE_REVENUE_BONUS
);
388 tb
= (float)tb
* pow(2.0, (double)bonus
/ 1000.0);
390 if (!establish_trade
) {
391 /* There will only be a full bonus if a new trade route is
392 * established. The one time bonus from Enter Marketplace is about one
393 * third of the one time bonus from Establish Trade Route. */
400 /**************************************************************************
401 Check if cities have an established trade route.
402 **************************************************************************/
403 bool have_cities_trade_route(const struct city
*pc1
, const struct city
*pc2
)
405 trade_routes_iterate(pc1
, route_to
) {
406 if (route_to
->id
== pc2
->id
) {
409 } trade_routes_iterate_end
;