Freeciv-3.1
Loading...
Searching...
No Matches
advbuilding.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 "rand.h"
20
21/* common */
22#include "ai.h"
23#include "city.h"
24#include "effects.h"
25#include "game.h"
26#include "movement.h"
27#include "player.h"
28#include "specialist.h"
29
30/* common/aicore */
31#include "path_finding.h"
32#include "pf_tools.h"
33
34/* server */
35#include "citytools.h"
36#include "plrhand.h"
37#include "srv_log.h"
38
39/* server/advisors */
40#include "advdata.h"
41#include "advtools.h"
42#include "infracache.h" /* adv_city */
43
44/* ai */
45#include "handicaps.h"
46
47#include "advbuilding.h"
48
49/**********************************************************************/
58static void calculate_city_clusters(struct player *pplayer)
59{
60 struct unit_type *punittype;
61 struct unit *ghost;
62 int range;
63 const struct civ_map *nmap = &(wld.map);
64
65 city_list_iterate(pplayer->cities, pcity) {
66 pcity->server.adv->downtown = 0;
68
69 if (num_role_units(action_id_get_role(ACTION_HELP_WONDER)) == 0) {
70 return; /* Ruleset has no help wonder unit */
71 }
72
73 punittype = best_role_unit_for_player(pplayer,
74 action_id_get_role(ACTION_HELP_WONDER));
75
76 if (punittype == NULL) {
77 /* Simulate future unit */
78 punittype = get_role_unit(action_id_get_role(ACTION_HELP_WONDER), 0);
79 }
80
81 fc_assert_msg(utype_can_do_action(punittype, ACTION_HELP_WONDER),
82 "Non existence of wonder helper unit not caught");
83
84 ghost = unit_virtual_create(pplayer, NULL, punittype, 0);
85 range = unit_move_rate(ghost) * 4;
86
87 city_list_iterate(pplayer->cities, pcity) {
88 struct pf_parameter parameter;
89 struct pf_map *pfm;
90 struct adv_city *city_data = pcity->server.adv;
91
92 unit_tile_set(ghost, pcity->tile);
93 pft_fill_unit_parameter(&parameter, nmap, ghost);
94 parameter.omniscience = !has_handicap(pplayer, H_MAP);
95 pfm = pf_map_new(&parameter);
96
97 pf_map_move_costs_iterate(pfm, ptile, move_cost, FALSE) {
98 struct city *acity = tile_city(ptile);
99
100 if (move_cost > range) {
101 break;
102 }
103 if (acity == NULL) {
104 continue;
105 }
106 if (city_owner(acity) == pplayer) {
107 city_data->downtown++;
108 }
110
111 pf_map_destroy(pfm);
113
115}
116
117/**********************************************************************/
120static void ba_human_wants(struct player *pplayer, struct city *wonder_city)
121{
122 /* Clear old building wants.
123 * Do this separately from the iteration over improvement types
124 * because each iteration could actually update more than one improvement,
125 * if improvements have improvements as requirements.
126 */
127 city_list_iterate(pplayer->cities, pcity) {
128 /* For a human player, any building is worth building until discarded */
129 improvement_iterate(pimprove) {
130 pcity->server.adv->building_want[improvement_index(pimprove)] = 1;
133
134 improvement_iterate(pimprove) {
135 const bool is_coinage = improvement_has_flag(pimprove, IF_GOLD);
136
137 /* Handle coinage specially because you can never complete coinage */
138 if (is_coinage
139 || can_player_build_improvement_later(pplayer, pimprove)) {
140 city_list_iterate(pplayer->cities, pcity) {
141 if (pcity != wonder_city && is_wonder(pimprove)) {
142 /* Only wonder city should build wonders! */
143 pcity->server.adv->building_want[improvement_index(pimprove)] = 0;
144 } else if (!is_coinage
145 && (!can_city_build_improvement_later(pcity, pimprove)
146 || (!is_improvement_productive(pcity, pimprove)))) {
147 /* Don't consider impossible or unproductive buildings */
148 pcity->server.adv->building_want[improvement_index(pimprove)] = 0;
149 } else if (city_has_building(pcity, pimprove)) {
150 /* Never want to build something we already have. */
151 pcity->server.adv->building_want[improvement_index(pimprove)] = 0;
152 }
153 /* else wait until a later turn */
155 } else {
156 /* An impossible improvement */
157 city_list_iterate(pplayer->cities, pcity) {
158 pcity->server.adv->building_want[improvement_index(pimprove)] = 0;
160 }
162
163#ifdef FREECIV_DEBUG
164 /* This logging is relatively expensive, so activate only if necessary */
165 city_list_iterate(pplayer->cities, pcity) {
166 improvement_iterate(pimprove) {
167 if (pcity->server.adv->building_want[improvement_index(pimprove)] != 0) {
168 CITY_LOG(LOG_DEBUG, pcity, "want to build %s with " ADV_WANT_PRINTF,
169 improvement_rule_name(pimprove),
170 pcity->server.adv->building_want[improvement_index(pimprove)]);
171 }
174#endif /* FREECIV_DEBUG */
175}
176
177/**********************************************************************/
180void building_advisor(struct player *pplayer)
181{
182 struct adv_data *adv = adv_data_get(pplayer, NULL);
183 struct city *wonder_city = game_city_by_number(adv->wonder_city);
184
185 CALL_FUNC_EACH_AI(build_adv_init, pplayer);
186
187 if (wonder_city && city_owner(wonder_city) != pplayer) {
188 /* We lost it to the enemy! */
189 adv->wonder_city = 0;
190 wonder_city = NULL;
191 }
192
193 /* Preliminary analysis - find our Wonder City. Also check if it
194 * is sane to continue building the wonder in it. If either does
195 * not check out, make a Wonder City. */
196 if (NULL == wonder_city
197 || 0 >= wonder_city->surplus[O_SHIELD]
198 || VUT_UTYPE == wonder_city->production.kind /* changed to defender? */
199 || !is_wonder(wonder_city->production.value.building)
200 || !can_city_build_improvement_now(wonder_city,
201 wonder_city->production.value.building)
202 || !is_improvement_productive(wonder_city,
203 wonder_city->production.value.building)) {
204 /* Find a new wonder city! */
205 int best_candidate_value = 0;
206 struct city *best_candidate = NULL;
207 /* Whether ruleset has a help wonder unit type */
208 bool has_help =
209 (num_role_units(action_id_get_role(ACTION_HELP_WONDER)) > 0);
210
212
213 city_list_iterate(pplayer->cities, pcity) {
214 int value = pcity->surplus[O_SHIELD];
215 Continent_id place = tile_continent(pcity->tile);
216 struct adv_city *city_data = pcity->server.adv;
217
218 if (is_ai(pplayer)) {
219 bool result = TRUE;
220
221 /* AI has opportunity to say that this city cannot be
222 * wonder city */
223 CALL_PLR_AI_FUNC(consider_wonder_city, pplayer, pcity, &result);
224 if (!result) {
225 continue;
226 }
227 }
228
229 if (is_terrain_class_near_tile(&(wld.map), pcity->tile, TC_OCEAN)) {
230 value /= 2;
231 }
232
233 /* Downtown is the number of cities within a certain pf range.
234 * These may be able to help with caravans. Also look at the whole
235 * continent. */
236 if (first_role_unit_for_player(pplayer,
237 action_id_get_role(ACTION_HELP_WONDER))) {
238 value += city_data->downtown;
239
240 if (place >= 0) {
241 value += adv->stats.cities[place] / 8;
242 }
243 }
244
245 if (place >= 0 && adv->threats.continent[place] > 0) {
246 /* We have threatening neighbors: -25% */
247 value -= value / 4;
248 }
249
250 /* Require that there is at least some neighbors for wonder helpers,
251 * if ruleset supports it. */
252 if (value > best_candidate_value
253 && (!has_help || (place >= 0 && adv->stats.cities[place] > 5))
254 && (!has_help || city_data->downtown > 3)) {
255 best_candidate = pcity;
256 best_candidate_value = value;
257 }
259
260 if (best_candidate) {
261 CITY_LOG(LOG_DEBUG, best_candidate, "chosen as wonder-city!");
262 adv->wonder_city = best_candidate->id;
263 wonder_city = best_candidate;
264 }
265 }
266
267 if (is_ai(pplayer)) {
268 CALL_PLR_AI_FUNC(build_adv_prepare, pplayer, pplayer, adv);
269 CALL_PLR_AI_FUNC(build_adv_adjust_want, pplayer, pplayer, wonder_city);
270 } else {
271 ba_human_wants(pplayer, wonder_city);
272 }
273}
274
275/**********************************************************************/
278void building_advisor_choose(struct city *pcity, struct adv_choice *choice)
279{
280 struct player *plr = city_owner(pcity);
281 struct impr_type *chosen = NULL;
282 adv_want want = 0;
283
284 improvement_iterate(pimprove) {
285 int id;
286
287 if (is_wonder(pimprove)) {
288 continue; /* Humans should not be advised to build wonders or palace */
289 }
290
291 id = improvement_index(pimprove);
292 if (pcity->server.adv->building_want[id] > want
293 && can_city_build_improvement_now(pcity, pimprove)) {
294 want = pcity->server.adv->building_want[id];
295 chosen = pimprove;
296 }
298
299 choice->want = want;
300 choice->value.building = chosen;
301
302 if (chosen != NULL) {
303 choice->type = CT_BUILDING;
304
305 CITY_LOG(LOG_DEBUG, pcity, "advisor wants to build %s with want "
307 improvement_rule_name(chosen), want);
308 } else {
309 choice->type = CT_NONE;
310 }
311 choice->need_boat = FALSE;
312
313 /* Allow AI to override */
314 CALL_PLR_AI_FUNC(choose_building, plr, pcity, choice);
315}
316
317/**********************************************************************/
320void advisor_choose_build(struct player *pplayer, struct city *pcity)
321{
322 struct adv_choice choice;
323
324 building_advisor_choose(pcity, &choice);
325
326 if (valid_improvement(choice.value.building)) {
327 struct universal target = {
328 .kind = VUT_IMPROVEMENT,
329 .value = {.building = choice.value.building}
330 };
331
332 change_build_target(pplayer, pcity, &target, E_IMP_AUTO);
333 return;
334 }
335
336 /* Build the first thing we can think of (except moving small wonder). */
337 improvement_iterate(pimprove) {
338 if (can_city_build_improvement_now(pcity, pimprove)
339 && pimprove->genus != IG_SMALL_WONDER) {
340 struct universal target = {
341 .kind = VUT_IMPROVEMENT,
342 .value = {.building = pimprove}
343 };
344
345 change_build_target(pplayer, pcity, &target, E_IMP_AUTO);
346 return;
347 }
349}
#define action_id_get_role(act_id)
Definition actions.h:708
static void calculate_city_clusters(struct player *pplayer)
Definition advbuilding.c:58
void building_advisor(struct player *pplayer)
static void ba_human_wants(struct player *pplayer, struct city *wonder_city)
void building_advisor_choose(struct city *pcity, struct adv_choice *choice)
void advisor_choose_build(struct player *pplayer, struct city *pcity)
@ CT_NONE
Definition advchoice.h:37
@ CT_BUILDING
Definition advchoice.h:38
struct adv_data * adv_data_get(struct player *pplayer, bool *caller_closes)
Definition advdata.c:593
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1216
bool can_city_build_improvement_now(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:839
bool can_city_build_improvement_later(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:856
#define city_list_iterate(citylist, pcity)
Definition city.h:488
#define city_owner(_pcity_)
Definition city.h:543
#define city_list_iterate_end
Definition city.h:490
void change_build_target(struct player *pplayer, struct city *pcity, struct universal *target, enum event_type event)
Definition citytools.c:3075
int int id
Definition editgui_g.h:28
float adv_want
Definition fc_types.h:1206
#define ADV_WANT_PRINTF
Definition fc_types.h:1207
@ O_SHIELD
Definition fc_types.h:91
signed short Continent_id
Definition fc_types.h:342
struct world wld
Definition game.c:58
struct city * game_city_by_number(int id)
Definition game.c:102
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
const struct impr_type * valid_improvement(const struct impr_type *pimprove)
bool can_player_build_improvement_later(const struct player *p, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
bool is_improvement_productive(const struct city *pcity, const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
@ LOG_DEBUG
Definition log.h:34
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
void pf_map_destroy(struct pf_map *pfm)
#define pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
#define is_ai(plr)
Definition player.h:234
#define CITY_LOG(loglevel, pcity, msg,...)
Definition srv_log.h:83
enum choice_type type
Definition advchoice.h:46
adv_want want
Definition advchoice.h:48
universals_u value
Definition advchoice.h:47
bool need_boat
Definition advchoice.h:49
int downtown
Definition infracache.h:34
adv_want building_want[B_LAST]
Definition infracache.h:32
struct adv_data::@90 threats
struct adv_data::@92 stats
int * cities
Definition advdata.h:90
bool * continent
Definition advdata.h:59
int wonder_city
Definition advdata.h:50
Definition city.h:309
int surplus[O_LAST]
Definition city.h:343
int id
Definition city.h:315
struct universal production
Definition city.h:382
struct adv_city * adv
Definition city.h:435
struct city::@17::@19 server
struct civ_map::@41::@43 server
struct city_list * cities
Definition player.h:281
Definition unit.h:138
struct tile * tile
Definition unit.h:140
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:600
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_continent(_tile)
Definition tile.h:91
const struct impr_type * building
Definition fc_types.h:598
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1617
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1713
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1281
struct unit_type * first_role_unit_for_player(const struct player *pplayer, int role)
Definition unittype.c:2371
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2301
int num_role_units(int role)
Definition unittype.c:2251
struct unit_type * best_role_unit_for_player(const struct player *pplayer, int role)
Definition unittype.c:2346
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443