Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / common / traderoutes.c
blob10c4cfe8143ee83736db0f8c2b5cd5e803c2402b
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 /* utility */
19 #include "log.h"
21 /* common */
22 #include "city.h"
23 #include "effects.h"
24 #include "game.h"
25 #include "map.h"
26 #include "tile.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);
60 if (plr1 != plr2) {
61 struct player_diplstate *ds = player_diplstate_get(plr1, plr2);
63 if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) {
64 switch (ds->type) {
65 case DS_ALLIANCE:
66 return TRT_ALLY_IC;
67 case DS_WAR:
68 return TRT_ENEMY_IC;
69 case DS_TEAM:
70 return TRT_TEAM_IC;
71 case DS_ARMISTICE:
72 case DS_CEASEFIRE:
73 case DS_PEACE:
74 case DS_NO_CONTACT:
75 return TRT_IN_IC;
76 case DS_LAST:
77 fc_assert(ds->type != DS_LAST);
78 return TRT_IN_IC;
80 fc_assert(FALSE);
82 return TRT_IN_IC;
83 } else {
84 switch (ds->type) {
85 case DS_ALLIANCE:
86 return TRT_ALLY;
87 case DS_WAR:
88 return TRT_ENEMY;
89 case DS_TEAM:
90 return TRT_TEAM;
91 case DS_ARMISTICE:
92 case DS_CEASEFIRE:
93 case DS_PEACE:
94 case DS_NO_CONTACT:
95 return TRT_IN;
96 case DS_LAST:
97 fc_assert(ds->type != DS_LAST);
98 return TRT_IN;
100 fc_assert(FALSE);
102 return TRT_IN;
104 } else {
105 if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) {
106 return TRT_NATIONAL_IC;
107 } else {
108 return TRT_NATIONAL;
112 return TRT_LAST;
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) {
121 return 0;
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)) {
160 return type;
164 return TRT_LAST;
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)) {
186 return type;
190 return TRI_LAST;
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);
201 return &trtss[type];
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))
219 > 0));
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];
231 int num, i, j;
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. */
239 num = 0;
240 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
241 if (0 == pcity->trade[i]) {
242 continue;
244 for (j = num; j > 0 && (pcity->trade_value[i]
245 < pcity->trade_value[sorted[j - 1]]); j--) {
246 sorted[j] = sorted[j - 1];
248 sorted[j] = i;
249 num++;
252 /* No trade routes at all. */
253 if (0 == num) {
254 return 0;
257 /* Adjust number of concerned trade routes. */
258 num += 1 - max_trade_routes(pcity);
259 if (0 >= num) {
260 num = 1;
263 /* Return values. */
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);
273 return j;
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
280 can_cities_trade().
281 **************************************************************************/
282 bool can_establish_trade_route(const struct city *pc1, const struct city *pc2)
284 int trade = -1;
285 int maxpc1;
286 int maxpc2;
288 if (!pc1 || !pc2 || pc1 == pc2
289 || !can_cities_trade(pc1, pc2)
290 || have_cities_trade_route(pc1, pc2)) {
291 return FALSE;
294 /* First check if cities can have trade routes at all. */
295 maxpc1 = max_trade_routes(pc1);
296 if (maxpc1 <= 0) {
297 return FALSE;
299 maxpc2 = max_trade_routes(pc2);
300 if (maxpc2 <= 0) {
301 return FALSE;
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) {
308 return FALSE;
312 if (city_num_trade_routes(pc2) >= maxpc2) {
313 if (trade == -1) {
314 trade = trade_between_cities(pc1, pc2);
316 /* can we replace trade route? */
317 if (city_trade_removable(pc2, NULL) >= trade) {
318 return FALSE;
322 return TRUE;
325 /**************************************************************************
326 Return the trade that exists between these cities, assuming they have a
327 trade route.
328 **************************************************************************/
329 int trade_between_cities(const struct city *pc1, const struct city *pc2)
331 int bonus = 0;
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;
341 bonus /= 12;
344 return bonus;
347 /**************************************************************************
348 Return number of trade route city has
349 **************************************************************************/
350 int city_num_trade_routes(const struct city *pcity)
352 int i, n = 0;
354 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
355 if (pcity->trade[i] != 0) {
356 n++;
360 return n;
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
366 new city.
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)
375 int tb, bonus;
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) */
383 tb *= 3;
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. */
394 tb = (tb + 2) / 3;
397 return tb;
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) {
407 return TRUE;
409 } trade_routes_iterate_end;
411 return FALSE;