Freeciv-3.4
Loading...
Searching...
No Matches
traderoutes.c
Go to the documentation of this file.
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/* utility */
19#include "log.h"
20#include "rand.h"
21
22/* common */
23#include "city.h"
24#include "effects.h"
25#include "game.h"
26#include "map.h"
27#include "tile.h"
28#include "unittype.h"
29
30#include "traderoutes.h"
31
32const char *trade_route_type_names[] = {
33 "National", "NationalIC", "IN", "INIC", "Ally", "AllyIC",
34 "Enemy", "EnemyIC", "Team", "TeamIC"
35};
36
38 "Active", "Inactive", "Cancel"
39};
40
42
44
45/*********************************************************************/
48unsigned max_trade_routes(const struct city *pcity)
49{
51
52 return CLIP(0, eft, MAX_TRADE_ROUTES);
53}
54
55/*********************************************************************/
59 const struct city *pcity2)
60{
61 struct player *plr1 = city_owner(pcity1);
62 struct player *plr2 = city_owner(pcity2);
63
64 if (plr1 != plr2) {
65 struct player_diplstate *ds = player_diplstate_get(plr1, plr2);
66
67 if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) {
68 switch (ds->type) {
69 case DS_ALLIANCE:
70 return TRT_ALLY_IC;
71 case DS_WAR:
72 return TRT_ENEMY_IC;
73 case DS_TEAM:
74 return TRT_TEAM_IC;
75 case DS_ARMISTICE:
76 case DS_CEASEFIRE:
77 case DS_PEACE:
78 case DS_NO_CONTACT:
79 return TRT_IN_IC;
80 case DS_LAST:
81 fc_assert(ds->type != DS_LAST);
82 return TRT_IN_IC;
83 }
85
86 return TRT_IN_IC;
87 } else {
88 switch (ds->type) {
89 case DS_ALLIANCE:
90 return TRT_ALLY;
91 case DS_WAR:
92 return TRT_ENEMY;
93 case DS_TEAM:
94 return TRT_TEAM;
95 case DS_ARMISTICE:
96 case DS_CEASEFIRE:
97 case DS_PEACE:
98 case DS_NO_CONTACT:
99 return TRT_IN;
100 case DS_LAST:
101 fc_assert(ds->type != DS_LAST);
102 return TRT_IN;
103 }
105
106 return TRT_IN;
107 }
108 } else {
109 if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) {
110 return TRT_NATIONAL_IC;
111 } else {
112 return TRT_NATIONAL;
113 }
114 }
115
116 return TRT_LAST;
117}
118
119/*********************************************************************/
123{
124 if (type >= TRT_LAST) {
125 return 0;
126 }
127
128 return trtss[type].trade_pct;
129}
130
131/*********************************************************************/
135{
137
138 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
140
141 set->trade_pct = 100;
142 }
143}
144
145/*********************************************************************/
149{
151
153}
154
155/*********************************************************************/
159{
161
162 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
164 return type;
165 }
166 }
167
168 return TRT_LAST;
169}
170
171/*********************************************************************/
180
181/*********************************************************************/
196
197/*********************************************************************/
207
208/*********************************************************************/
214bool can_cities_trade(const struct city *pc1, const struct city *pc2)
215{
216 /* If you change the logic here, make sure to update the help in
217 * helptext_unit(). */
218 return (pc1 && pc2 && pc1 != pc2
220 || map_distance(pc1->tile, pc2->tile)
223 > 0));
224}
225
226/*********************************************************************/
233{
235 int num, i, j;
236
237 /* Sort trade route values. */
238 num = 0;
240 if (proute->goods->replace_priority <= priority) {
241 for (j = num;
242 j > 0 && proute->goods->replace_priority > sorted[j - 1]->goods->replace_priority;
243 j--) ;
244
245 /* Search place among same priority ones. */
246 for (; j > 0
247 && (proute->value < sorted[j - 1]->value)
248 && (proute->goods->replace_priority == sorted[j - 1]->goods->replace_priority) ;
249 j--) {
250 sorted[j] = sorted[j - 1];
251 }
252 sorted[j] = proute;
253 num++;
254 }
256
257 /* No trade routes at all. */
258 if (num == 0) {
259 return 0;
260 }
261
262 /* Adjust number of concerned trade routes. */
263 num += 1 - max_trade_routes(pcity);
264 if (num < 0) {
265 num = 1;
266 }
267
268 /* Return values. */
269 for (i = j = 0; i < num; i++) {
270 j += sorted[i]->value;
271 if (would_remove != nullptr) {
273 }
274 }
275
276 return j;
277}
278
279/*********************************************************************/
284bool can_establish_trade_route(const struct city *pc1, const struct city *pc2,
285 int priority)
286{
287 int trade = -1;
288 int maxpc1;
289 int maxpc2;
290
291 if (!pc1 || !pc2 || pc1 == pc2
294 return FALSE;
295 }
296
297 /* First check if cities can have trade routes at all. */
299 if (maxpc1 <= 0) {
300 return FALSE;
301 }
303 if (maxpc2 <= 0) {
304 return FALSE;
305 }
306
309 /* Can we replace trade route? */
310 if (city_trade_removable(pc1, priority, nullptr) >= trade) {
311 return FALSE;
312 }
313 }
314
316 if (trade == -1) {
318 }
319 /* Can we replace trade route? */
320 if (city_trade_removable(pc2, priority, nullptr) >= trade) {
321 return FALSE;
322 }
323 }
324
325 return TRUE;
326}
327
328/*********************************************************************/
332int trade_base_between_cities(const struct city *pc1, const struct city *pc2)
333{
334 int bonus = 0;
335
336 if (pc1 == nullptr || pc1->tile == nullptr
337 || pc2 == nullptr || pc2->tile == nullptr) {
338 return 0;
339 }
340
342 /* Classic Freeciv */
343 int real_dist = real_map_distance(pc1->tile, pc2->tile);
348
349 bonus = weighted_distance
351 } else if (game.info.trade_revenue_style == TRS_SIMPLE) {
352 /* Simple revenue style */
353 bonus = (pc1->citizen_base[O_TRADE] + pc2->citizen_base[O_TRADE] + 4)
354 * 3;
355 }
356
357 bonus = bonus
359 / 100;
360
361 bonus /= 12;
362
363 return bonus;
364}
365
366/*********************************************************************/
369int trade_from_route(const struct city *pc1, const struct trade_route *route,
370 int base)
371{
372 int val;
373
374 if (route->dir == RDIR_TO) {
375 val = base * route->goods->to_pct / 100;
376
377 if (route->goods->to_pct > 0) {
378 val = MAX(val, game.info.min_trade_route_val);
379 }
380 } else {
381 val = base * route->goods->from_pct / 100;
382
383 if (route->goods->from_pct > 0) {
384 val = MAX(val, game.info.min_trade_route_val);
385 }
386 }
387
388 return val;
389}
390
391/*********************************************************************/
395{
396 return trade_route_list_size(pcity->routes);
397}
398
399/*********************************************************************/
402static int best_value(const void *a, const void *b)
403{
404 return *(int *)a < *(int *)b;
405}
406
407/*********************************************************************/
410static int max_tile_trade(const struct city *pcity)
411{
412 int i, total = 0;
413 int radius_sq = city_map_radius_sq_get(pcity);
414 int tile_trade[city_map_tiles(radius_sq)];
415 size_t size = 0;
417 const struct civ_map *nmap = &(wld.map);
418
419 if (pcity->tile == nullptr) {
420 return 0;
421 }
422
423 city_map_iterate(radius_sq, cindex, cx, cy) {
424 struct tile *ptile = city_map_to_tile(nmap, pcity->tile, radius_sq, cx, cy);
425
426 if (ptile == nullptr) {
427 continue;
428 }
429
430 if (is_free_worked_index(cindex)) {
431 total += city_tile_output(pcity, ptile, is_celebrating, O_TRADE);
432 continue;
433 }
434
435 if (!city_can_work_tile(pcity, ptile)) {
436 continue;
437 }
438
440 O_TRADE);
442
444
445 for (i = 0; i < pcity->size && i < size; i++) {
446 total += tile_trade[i];
447 }
448
449 return total;
450}
451
452/*********************************************************************/
455int max_trade_prod(const struct city *pcity)
456{
457 /* Trade tile base */
459
460 /* Add trade routes values */
461 trade_partners_iterate(pcity, partner) {
464
465 return trade_prod;
466}
467
468/*********************************************************************/
479 const struct city *pc2,
480 const struct unit_type *ut,
481 struct goods_type *pgood,
482 const bool establish_trade)
483{
484 int tb = 0, bonus = 0;
486
487 if (trtss[trtype].bonus_type == TBONUS_NONE) {
488 return 0;
489 }
490
492 /* Should this be real_map_distance? */
493 int distance = map_distance(pc1->tile, pc2->tile);
495 = ((100 - game.info.trade_world_rel_pct) * distance
497 * (distance * 40 / MAX(MAP_NATIVE_WIDTH, MAP_NATIVE_HEIGHT))) / 100;
498
499 tb = weighted_distance + 10;
500 tb = (tb * (pc1->surplus[O_TRADE] + pc2->surplus[O_TRADE])) / 24;
502 /* Logarithmic bonus */
503 int distance = real_map_distance(pc1->tile, pc2->tile);
505 = ((100 - game.info.trade_world_rel_pct) * distance
507 * (distance * 40 / MAX(MAP_NATIVE_WIDTH, MAP_NATIVE_HEIGHT))) / 100;
508
510 + max_trade_prod(pc1) + max_trade_prod(pc2)) * 2, 2);
511 }
512
513 if (pgood != nullptr) {
514 tb = tb * pgood->onetime_pct / 100;
515 }
516
517 /* Trade_revenue_bonus increases revenue by power of 2 in milimes */
518 bonus = get_target_bonus_effects(nullptr,
519 &(const struct req_context) {
520 .player = city_owner(pc1),
521 .city = pc1,
522 .tile = city_tile(pc1),
523 /* Putting .unit things like unit veterancy
524 * in the scope give little gameplay
525 * and overcomplicate the AI logic */
526 .unittype = ut,
527 /* Could be used to reduce the one time
528 * bonus if no trade route is
529 * established. */
530 .action = action_by_number(
534 ),
535 },
536 &(const struct req_context) {
537 .player = city_owner(pc2),
538 .city = pc2,
539 .tile = city_tile(pc2),
540 },
542
543 /* Be mercy full to players with small amounts. Round up. */
544 tb = ceil((float)tb * pow(2.0, (double)bonus / 1000.0));
545
546 return tb;
547}
548
549/*********************************************************************/
552bool have_cities_trade_route(const struct city *pc1, const struct city *pc2)
553{
555 if (route_to->id == pc2->id) {
556 return TRUE;
557 }
559
560 return FALSE;
561}
562
563/*********************************************************************/
566void goods_init(void)
567{
568 int i;
569
570 for (i = 0; i < MAX_GOODS_TYPES; i++) {
571 goods[i].id = i;
572
575 goods[i].helptext = nullptr;
576 }
577}
578
579/*********************************************************************/
582void goods_free(void)
583{
584 int i;
585
586 for (i = 0; i < MAX_GOODS_TYPES; i++) {
588
589 if (goods[i].helptext != nullptr) {
590 strvec_destroy(goods[i].helptext);
591 goods[i].helptext = nullptr;
592 }
593 }
594}
595
596/*********************************************************************/
600{
601 fc_assert_ret_val(pgood != nullptr, -1);
602
603 return pgood->id;
604}
605
606/*********************************************************************/
613{
614 fc_assert_ret_val(pgood != nullptr, -1);
615
616 return pgood - goods;
617}
618
619/*********************************************************************/
623{
624 fc_assert_ret_val(id >= 0 && id < game.control.num_goods_types, nullptr);
625
626 return &goods[id];
627}
628
629/*********************************************************************/
633{
634 return name_translation_get(&pgood->name);
635}
636
637/*********************************************************************/
640const char *goods_rule_name(struct goods_type *pgood)
641{
642 return rule_name_get(&pgood->name);
643}
644
645/*********************************************************************/
650{
651 const char *qs;
652
653 if (name == nullptr) {
654 return nullptr;
655 }
656
657 qs = Qn_(name);
658
661 return pgood;
662 }
664
665 return nullptr;
666}
667
668/*********************************************************************/
673{
676 return pgood;
677 }
679
680 return nullptr;
681}
682
683/*********************************************************************/
686bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
687{
688 return BV_ISSET(pgood->flags, flag);
689}
690
691/*********************************************************************/
695 const struct goods_type *pgood,
696 const struct unit *punit)
697{
698 return are_reqs_active(&(const struct req_context) {
699 .player = city_owner(pcity),
700 .city = pcity,
701 .tile = city_tile(pcity),
702 .unit = punit,
703 .unittype = punit ? unit_type_get(punit) : nullptr,
704 },
705 nullptr,
706 &pgood->reqs, RPT_CERTAIN);
707}
708
709/*********************************************************************/
712bool city_receives_goods(const struct city *pcity,
713 const struct goods_type *pgood)
714{
716 if (proute->goods == pgood
717 && (proute->dir == RDIR_TO || proute->dir == RDIR_BIDIRECTIONAL)) {
718 struct city *tcity = game_city_by_number(proute->partner);
721
723 return TRUE;
724 }
725
728
729 if (settings->cancelling == TRI_ACTIVE) {
730 return TRUE;
731 }
732 }
734
735 return FALSE;
736}
737
738/*********************************************************************/
745struct goods_type *goods_from_city_to_unit(const struct city *src,
746 const struct unit *punit)
747{
748 int i = 0;
749 int prio = -1;
751
753 if (goods_can_be_provided(src, pgood, punit)) {
754 if (pgood->select_priority >= prio) {
755 if (pgood->select_priority > prio) {
756 /* New highest priority */
757 i = 0;
759 }
760
761 potential[i++] = pgood;
762 }
763 }
765
766 if (i == 0) {
767 return nullptr;
768 }
769
770 return potential[fc_rand(i)];
771}
772
773/*********************************************************************/
781 const struct city *homecity)
782{
784 return goods_from_city_to_unit(homecity, punit);
785 }
786
787 return punit->carrying;
788}
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
bool base_city_celebrating(const struct city *pcity)
Definition city.c:1692
struct tile * city_map_to_tile(const struct civ_map *nmap, const struct tile *city_center, int city_radius_sq, int city_map_x, int city_map_y)
Definition city.c:305
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
int city_tile_output(const struct city *pcity, const struct tile *ptile, bool is_celebrating, Output_type_id otype)
Definition city.c:1338
int city_map_tiles(int city_radius_sq)
Definition city.c:171
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1511
#define city_tile(_pcity_)
Definition city.h:565
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
#define city_owner(_pcity_)
Definition city.h:564
#define city_map_iterate_end
Definition city.h:175
#define city_map_iterate(_radius_sq, _index, _x, _y)
Definition city.h:171
#define is_free_worked_index(city_tile_index)
Definition city.h:886
char * incite_cost
Definition comments.c:77
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2977
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
int int id
Definition editgui_g.h:28
struct @22::@23 reqs
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:842
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct req_context *other_context, enum effect_type effect_type)
Definition effects.c:744
#define MAX_TRADE_ROUTES
Definition fc_types.h:954
int Goods_type_id
Definition fc_types.h:248
#define MAX_GOODS_TYPES
Definition fc_types.h:51
@ RPT_CERTAIN
Definition fc_types.h:516
@ O_TRADE
Definition fc_types.h:103
#define Qn_(String)
Definition fcintl.h:89
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct city * game_city_by_number(int id)
Definition game.c:106
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:675
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * name_translation_get(const struct name_translation *ptrans)
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:325
#define fc_rand(_size)
Definition rand.h:56
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
static struct setting settings[]
Definition settings.c:1494
#define CLIP(lower, current, upper)
Definition shared.h:57
#define MAX(x, y)
Definition shared.h:54
SPECPQ_PRIORITY_TYPE priority
Definition specpq.h:86
size_t size
Definition specvec.h:72
void strvec_destroy(struct strvec *psv)
Definition city.h:318
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
bool ruledit_disabled
int select_priority
struct strvec * helptext
enum goods_selection_method goods_selection
enum trade_revenue_style trade_revenue_style
enum caravan_bonus_style caravan_bonus_style
Definition tile.h:50
Definition unit.h:140
struct tile * tile
Definition unit.h:142
struct goods_type * carrying
Definition unit.h:189
struct civ_map map
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int max_trade_prod(const struct city *pcity)
bool can_cities_trade(const struct city *pc1, const struct city *pc2)
enum trade_route_type cities_trade_route_type(const struct city *pcity1, const struct city *pcity2)
Definition traderoutes.c:58
const char * trade_route_cancelling_type_names[]
Definition traderoutes.c:37
int trade_route_type_trade_pct(enum trade_route_type type)
int trade_base_between_cities(const struct city *pc1, const struct city *pc2)
bool goods_can_be_provided(const struct city *pcity, const struct goods_type *pgood, const struct unit *punit)
int city_num_trade_routes(const struct city *pcity)
Goods_type_id goods_number(const struct goods_type *pgood)
static struct goods_type goods[MAX_GOODS_TYPES]
Definition traderoutes.c:43
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
enum trade_route_illegal_cancelling trade_route_cancelling_type_by_name(const char *name)
const char * trade_route_type_name(enum trade_route_type type)
static int max_tile_trade(const struct city *pcity)
struct trade_route_settings * trade_route_settings_by_type(enum trade_route_type type)
struct trade_route_settings trtss[TRT_LAST]
Definition traderoutes.c:41
struct goods_type * goods_by_rule_name(const char *name)
int trade_from_route(const struct city *pc1, const struct trade_route *route, int base)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_from_city_to_unit(const struct city *src, const struct unit *punit)
struct goods_type * unit_current_goods(const struct unit *punit, const struct city *homecity)
unsigned max_trade_routes(const struct city *pcity)
Definition traderoutes.c:48
const char * goods_name_translation(struct goods_type *pgood)
void trade_route_types_init(void)
Goods_type_id goods_index(const struct goods_type *pgood)
static int best_value(const void *a, const void *b)
struct goods_type * goods_by_translated_name(const char *name)
int city_trade_removable(const struct city *pcity, int priority, struct trade_route_list *would_remove)
bool can_establish_trade_route(const struct city *pc1, const struct city *pc2, int priority)
struct goods_type * goods_by_number(Goods_type_id id)
const char * trade_route_cancelling_type_name(enum trade_route_illegal_cancelling type)
void goods_init(void)
bool city_receives_goods(const struct city *pcity, const struct goods_type *pgood)
void goods_free(void)
const char * trade_route_type_names[]
Definition traderoutes.c:32
enum trade_route_type trade_route_type_by_name(const char *name)
bool have_cities_trade_route(const struct city *pc1, const struct city *pc2)
int get_caravan_enter_city_trade_bonus(const struct city *pc1, const struct city *pc2, const struct unit_type *ut, struct goods_type *pgood, const bool establish_trade)
#define goods_type_iterate_end
trade_route_illegal_cancelling
Definition traderoutes.h:29
@ TRI_LAST
Definition traderoutes.h:33
@ TRI_ACTIVE
Definition traderoutes.h:30
#define goods_type_iterate(_p)
#define trade_routes_iterate_end
#define trade_partners_iterate_end
#define trade_routes_iterate(c, proute)
#define trade_partners_iterate(c, p)
trade_route_type
Definition traderoutes.h:37
@ TRT_NATIONAL_IC
Definition traderoutes.h:39
@ TRT_TEAM_IC
Definition traderoutes.h:47
@ TRT_ALLY_IC
Definition traderoutes.h:43
@ TRT_IN_IC
Definition traderoutes.h:41
@ TRT_NATIONAL
Definition traderoutes.h:38
@ TRT_LAST
Definition traderoutes.h:48
@ TRT_IN
Definition traderoutes.h:40
@ TRT_TEAM
Definition traderoutes.h:46
@ TRT_ALLY
Definition traderoutes.h:42
@ TRT_ENEMY_IC
Definition traderoutes.h:45
@ TRT_ENEMY
Definition traderoutes.h:44
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
#define MAP_NATIVE_WIDTH
#define MAP_NATIVE_HEIGHT