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 /* common */
19 #include "city.h"
20 #include "game.h"
21 #include "map.h"
22 #include "player.h"
23 #include "tile.h"
24
25 /* server */
26 #include "maphand.h"
27
28 /* server/advisors */
29 #include "advbuilding.h"
30 #include "autosettlers.h"
31
32 #include "infracache.h"
33
34 /* cache activities within the city map */
35 struct worker_activity_cache {
36 int act[ACTIVITY_LAST];
37 int extra[MAX_EXTRA_TYPES];
38 int rmextra[MAX_EXTRA_TYPES];
39 };
40
41 static int adv_calc_irrigate_transform(const struct city *pcity,
42 const struct tile *ptile);
43 static int adv_calc_mine_transform(const struct city *pcity, const struct tile *ptile);
44 static int adv_calc_transform(const struct city *pcity,
45 const struct tile *ptile);
46 static int adv_calc_extra(const struct city *pcity, const struct tile *ptile,
47 const struct extra_type *pextra);
48 static int adv_calc_rmextra(const struct city *pcity, const struct tile *ptile,
49 const struct extra_type *pextra);
50
51 /**************************************************************************
52 Calculate the benefit of irrigating the given tile.
53
54 The return value is the goodness of the tile after the irrigation. This
55 should be compared to the goodness of the tile currently (see
56 city_tile_value(); note that this depends on the AI's weighting
57 values).
58 **************************************************************************/
adv_calc_irrigate_transform(const struct city * pcity,const struct tile * ptile)59 static int adv_calc_irrigate_transform(const struct city *pcity,
60 const struct tile *ptile)
61 {
62 int goodness;
63 struct terrain *old_terrain, *new_terrain;
64
65 fc_assert_ret_val(ptile != NULL, -1);
66
67 old_terrain = tile_terrain(ptile);
68 new_terrain = old_terrain->irrigation_result;
69
70 if (new_terrain != old_terrain && new_terrain != T_NONE) {
71 struct tile *vtile;
72
73 if (tile_city(ptile) && terrain_has_flag(new_terrain, TER_NO_CITIES)) {
74 /* Not a valid activity. */
75 return -1;
76 }
77 /* Irrigation would change the terrain type, clearing conflicting
78 * extras in the process. Calculate the benefit of doing so. */
79 vtile = tile_virtual_new(ptile);
80
81 tile_change_terrain(vtile, new_terrain);
82 goodness = city_tile_value(pcity, vtile, 0, 0);
83 tile_virtual_destroy(vtile);
84
85 return goodness;
86 } else {
87 return -1;
88 }
89 }
90
91 /**************************************************************************
92 Calculate the benefit of mining the given tile.
93
94 The return value is the goodness of the tile after the mining. This
95 should be compared to the goodness of the tile currently (see
96 city_tile_value(); note that this depends on the AI's weighting
97 values).
98 **************************************************************************/
adv_calc_mine_transform(const struct city * pcity,const struct tile * ptile)99 static int adv_calc_mine_transform(const struct city *pcity, const struct tile *ptile)
100 {
101 int goodness;
102 struct terrain *old_terrain, *new_terrain;
103
104 fc_assert_ret_val(ptile != NULL, -1);
105
106 old_terrain = tile_terrain(ptile);
107 new_terrain = old_terrain->mining_result;
108
109 if (old_terrain != new_terrain && new_terrain != T_NONE) {
110 struct tile *vtile;
111
112 if (tile_city(ptile) && terrain_has_flag(new_terrain, TER_NO_CITIES)) {
113 /* Not a valid activity. */
114 return -1;
115 }
116 /* Mining would change the terrain type, clearing conflicting
117 * extras in the process. Calculate the benefit of doing so. */
118 vtile = tile_virtual_new(ptile);
119
120 tile_change_terrain(vtile, new_terrain);
121 goodness = city_tile_value(pcity, vtile, 0, 0);
122 tile_virtual_destroy(vtile);
123
124 return goodness;
125 } else {
126 return -1;
127 }
128 }
129
130 /**************************************************************************
131 Calculate the benefit of transforming the given tile.
132
133 The return value is the goodness of the tile after the transform. This
134 should be compared to the goodness of the tile currently (see
135 city_tile_value(); note that this depends on the AI's weighting
136 values).
137 **************************************************************************/
adv_calc_transform(const struct city * pcity,const struct tile * ptile)138 static int adv_calc_transform(const struct city *pcity,
139 const struct tile *ptile)
140 {
141 int goodness;
142 struct tile *vtile;
143 struct terrain *old_terrain, *new_terrain;
144
145 fc_assert_ret_val(ptile != NULL, -1);
146
147 old_terrain = tile_terrain(ptile);
148 new_terrain = old_terrain->transform_result;
149
150 if (old_terrain == new_terrain || new_terrain == T_NONE) {
151 return -1;
152 }
153
154 if (!terrain_surroundings_allow_change(ptile, new_terrain)) {
155 /* Can't do this terrain conversion here. */
156 return -1;
157 }
158
159 if (tile_city(ptile) && terrain_has_flag(new_terrain, TER_NO_CITIES)) {
160 return -1;
161 }
162
163 vtile = tile_virtual_new(ptile);
164 tile_change_terrain(vtile, new_terrain);
165 goodness = city_tile_value(pcity, vtile, 0, 0);
166 tile_virtual_destroy(vtile);
167
168 return goodness;
169 }
170
171 /**************************************************************************
172 Calculate the benefit of building an extra at the given tile.
173
174 The return value is the goodness of the tile after the extra is built.
175 This should be compared to the goodness of the tile currently (see
176 city_tile_value(); note that this depends on the AI's weighting
177 values).
178
179 This function does not calculate the benefit of being able to quickly
180 move units (i.e., of connecting the civilization). See road_bonus() for
181 that calculation.
182 **************************************************************************/
adv_calc_extra(const struct city * pcity,const struct tile * ptile,const struct extra_type * pextra)183 static int adv_calc_extra(const struct city *pcity, const struct tile *ptile,
184 const struct extra_type *pextra)
185 {
186 int goodness = -1;
187
188 fc_assert_ret_val(ptile != NULL, -1);
189
190 if (player_can_build_extra(pextra, city_owner(pcity), ptile)) {
191 struct tile *vtile = tile_virtual_new(ptile);
192
193 tile_add_extra(vtile, pextra);
194
195 extra_type_iterate(cextra) {
196 if (tile_has_extra(vtile, cextra)
197 && !can_extras_coexist(pextra, cextra)) {
198 tile_remove_extra(vtile, cextra);
199 }
200 } extra_type_iterate_end;
201
202 goodness = city_tile_value(pcity, vtile, 0, 0);
203 tile_virtual_destroy(vtile);
204 }
205
206 return goodness;
207 }
208
209 /**************************************************************************
210 Calculate the benefit of removing an extra from the given tile.
211
212 The return value is the goodness of the tile after the extra is removed.
213 This should be compared to the goodness of the tile currently (see
214 city_tile_value(); note that this depends on the AI's weighting
215 values).
216 **************************************************************************/
adv_calc_rmextra(const struct city * pcity,const struct tile * ptile,const struct extra_type * pextra)217 static int adv_calc_rmextra(const struct city *pcity, const struct tile *ptile,
218 const struct extra_type *pextra)
219 {
220 int goodness = -1;
221
222 fc_assert_ret_val(ptile != NULL, -1);
223
224 if (player_can_remove_extra(pextra, city_owner(pcity), ptile)) {
225 struct tile *vtile = tile_virtual_new(ptile);
226
227 tile_remove_extra(vtile, pextra);
228
229 goodness = city_tile_value(pcity, vtile, 0, 0);
230 tile_virtual_destroy(vtile);
231 }
232
233 return goodness;
234 }
235
236 /**************************************************************************
237 Do all tile improvement calculations and cache them for later.
238
239 These values are used in settler_evaluate_improvements() so this function
240 must be called before doing that. Currently this is only done when handling
241 auto-settlers or when the AI contemplates building worker units.
242 **************************************************************************/
initialize_infrastructure_cache(struct player * pplayer)243 void initialize_infrastructure_cache(struct player *pplayer)
244 {
245 city_list_iterate(pplayer->cities, pcity) {
246 struct tile *pcenter = city_tile(pcity);
247 int radius_sq = city_map_radius_sq_get(pcity);
248
249 city_map_iterate(radius_sq, city_index, city_x, city_y) {
250 as_transform_activity_iterate(act) {
251 adv_city_worker_act_set(pcity, city_index, act, -1);
252 } as_transform_activity_iterate_end;
253 } city_map_iterate_end;
254
255 city_tile_iterate_index(radius_sq, pcenter, ptile, cindex) {
256 adv_city_worker_act_set(pcity, cindex, ACTIVITY_MINE,
257 adv_calc_mine_transform(pcity, ptile));
258 adv_city_worker_act_set(pcity, cindex, ACTIVITY_IRRIGATE,
259 adv_calc_irrigate_transform(pcity, ptile));
260 adv_city_worker_act_set(pcity, cindex, ACTIVITY_TRANSFORM,
261 adv_calc_transform(pcity, ptile));
262
263 /* road_bonus() is handled dynamically later; it takes into
264 * account settlers that have already been assigned to building
265 * roads this turn. */
266 extra_type_iterate(pextra) {
267 /* We have no use for extra value, if workers cannot be assigned
268 * to build it, so don't use time to calculate values otherwise */
269 if (pextra->buildable
270 && is_extra_caused_by_worker_action(pextra)) {
271 adv_city_worker_extra_set(pcity, cindex, pextra,
272 adv_calc_extra(pcity, ptile, pextra));
273 } else {
274 adv_city_worker_extra_set(pcity, cindex, pextra, 0);
275 }
276 if (tile_has_extra(ptile, pextra) && is_extra_removed_by_worker_action(pextra)) {
277 adv_city_worker_rmextra_set(pcity, cindex, pextra,
278 adv_calc_rmextra(pcity, ptile, pextra));
279 } else {
280 adv_city_worker_rmextra_set(pcity, cindex, pextra, 0);
281 }
282 } extra_type_iterate_end;
283 } city_tile_iterate_index_end;
284 } city_list_iterate_end;
285 }
286
287 /**************************************************************************
288 Returns a measure of goodness of a tile to pcity.
289
290 FIXME: foodneed and prodneed are always 0.
291 **************************************************************************/
city_tile_value(const struct city * pcity,const struct tile * ptile,int foodneed,int prodneed)292 int city_tile_value(const struct city *pcity, const struct tile *ptile,
293 int foodneed, int prodneed)
294 {
295 int food = city_tile_output_now(pcity, ptile, O_FOOD);
296 int shield = city_tile_output_now(pcity, ptile, O_SHIELD);
297 int trade = city_tile_output_now(pcity, ptile, O_TRADE);
298 int value = 0;
299
300 /* Each food, trade, and shield gets a certain weighting. We also benefit
301 * tiles that have at least one of an item - this promotes balance and
302 * also accounts for INC_TILE effects. */
303 value += food * FOOD_WEIGHTING;
304 if (food > 0) {
305 value += FOOD_WEIGHTING / 2;
306 }
307 value += shield * SHIELD_WEIGHTING;
308 if (shield > 0) {
309 value += SHIELD_WEIGHTING / 2;
310 }
311 value += trade * TRADE_WEIGHTING;
312 if (trade > 0) {
313 value += TRADE_WEIGHTING / 2;
314 }
315
316 return value;
317 }
318
319 /**************************************************************************
320 Set the value for activity 'doing' on tile 'city_tile_index' of
321 city 'pcity'.
322 **************************************************************************/
adv_city_worker_act_set(struct city * pcity,int city_tile_index,enum unit_activity act_id,int value)323 void adv_city_worker_act_set(struct city *pcity, int city_tile_index,
324 enum unit_activity act_id, int value)
325 {
326 if (pcity->server.adv->act_cache_radius_sq
327 != city_map_radius_sq_get(pcity)) {
328 log_debug("update activity cache for %s: radius_sq changed from "
329 "%d to %d", city_name_get(pcity),
330 pcity->server.adv->act_cache_radius_sq,
331 city_map_radius_sq_get(pcity));
332 adv_city_update(pcity);
333 }
334
335 fc_assert_ret(NULL != pcity);
336 fc_assert_ret(NULL != pcity->server.adv);
337 fc_assert_ret(NULL != pcity->server.adv->act_cache);
338 fc_assert_ret(pcity->server.adv->act_cache_radius_sq
339 == city_map_radius_sq_get(pcity));
340 fc_assert_ret(city_tile_index < city_map_tiles_from_city(pcity));
341
342 (pcity->server.adv->act_cache[city_tile_index]).act[act_id] = value;
343 }
344
345 /**************************************************************************
346 Return the value for activity 'doing' on tile 'city_tile_index' of
347 city 'pcity'.
348 **************************************************************************/
adv_city_worker_act_get(const struct city * pcity,int city_tile_index,enum unit_activity act_id)349 int adv_city_worker_act_get(const struct city *pcity, int city_tile_index,
350 enum unit_activity act_id)
351 {
352 fc_assert_ret_val(NULL != pcity, 0);
353 fc_assert_ret_val(NULL != pcity->server.adv, 0);
354 fc_assert_ret_val(NULL != pcity->server.adv->act_cache, 0);
355 fc_assert_ret_val(pcity->server.adv->act_cache_radius_sq
356 == city_map_radius_sq_get(pcity), 0);
357 fc_assert_ret_val(city_tile_index < city_map_tiles_from_city(pcity), 0);
358
359 return (pcity->server.adv->act_cache[city_tile_index]).act[act_id];
360 }
361
362 /**************************************************************************
363 Set the value for extra on tile 'city_tile_index' of
364 city 'pcity'.
365 **************************************************************************/
adv_city_worker_extra_set(struct city * pcity,int city_tile_index,const struct extra_type * pextra,int value)366 void adv_city_worker_extra_set(struct city *pcity, int city_tile_index,
367 const struct extra_type *pextra, int value)
368 {
369 if (pcity->server.adv->act_cache_radius_sq
370 != city_map_radius_sq_get(pcity)) {
371 log_debug("update activity cache for %s: radius_sq changed from "
372 "%d to %d", city_name_get(pcity),
373 pcity->server.adv->act_cache_radius_sq,
374 city_map_radius_sq_get(pcity));
375 adv_city_update(pcity);
376 }
377
378 fc_assert_ret(NULL != pcity);
379 fc_assert_ret(NULL != pcity->server.adv);
380 fc_assert_ret(NULL != pcity->server.adv->act_cache);
381 fc_assert_ret(pcity->server.adv->act_cache_radius_sq
382 == city_map_radius_sq_get(pcity));
383 fc_assert_ret(city_tile_index < city_map_tiles_from_city(pcity));
384
385 (pcity->server.adv->act_cache[city_tile_index]).extra[extra_index(pextra)] = value;
386 }
387
388 /**************************************************************************
389 Set the value for extra removal on tile 'city_tile_index' of
390 city 'pcity'.
391 **************************************************************************/
adv_city_worker_rmextra_set(struct city * pcity,int city_tile_index,const struct extra_type * pextra,int value)392 void adv_city_worker_rmextra_set(struct city *pcity, int city_tile_index,
393 const struct extra_type *pextra, int value)
394 {
395 if (pcity->server.adv->act_cache_radius_sq
396 != city_map_radius_sq_get(pcity)) {
397 log_debug("update activity cache for %s: radius_sq changed from "
398 "%d to %d", city_name_get(pcity),
399 pcity->server.adv->act_cache_radius_sq,
400 city_map_radius_sq_get(pcity));
401 adv_city_update(pcity);
402 }
403
404 fc_assert_ret(NULL != pcity);
405 fc_assert_ret(NULL != pcity->server.adv);
406 fc_assert_ret(NULL != pcity->server.adv->act_cache);
407 fc_assert_ret(pcity->server.adv->act_cache_radius_sq
408 == city_map_radius_sq_get(pcity));
409 fc_assert_ret(city_tile_index < city_map_tiles_from_city(pcity));
410
411 (pcity->server.adv->act_cache[city_tile_index]).rmextra[extra_index(pextra)] = value;
412 }
413
414 /**************************************************************************
415 Return the value for extra on tile 'city_tile_index' of
416 city 'pcity'.
417 **************************************************************************/
adv_city_worker_extra_get(const struct city * pcity,int city_tile_index,const struct extra_type * pextra)418 int adv_city_worker_extra_get(const struct city *pcity, int city_tile_index,
419 const struct extra_type *pextra)
420 {
421 fc_assert_ret_val(NULL != pcity, 0);
422 fc_assert_ret_val(NULL != pcity->server.adv, 0);
423 fc_assert_ret_val(NULL != pcity->server.adv->act_cache, 0);
424 fc_assert_ret_val(pcity->server.adv->act_cache_radius_sq
425 == city_map_radius_sq_get(pcity), 0);
426 fc_assert_ret_val(city_tile_index < city_map_tiles_from_city(pcity), 0);
427
428 return (pcity->server.adv->act_cache[city_tile_index]).extra[extra_index(pextra)];
429 }
430
431 /**************************************************************************
432 Return the value for extra removal on tile 'city_tile_index' of
433 city 'pcity'.
434 **************************************************************************/
adv_city_worker_rmextra_get(const struct city * pcity,int city_tile_index,const struct extra_type * pextra)435 int adv_city_worker_rmextra_get(const struct city *pcity, int city_tile_index,
436 const struct extra_type *pextra)
437 {
438 fc_assert_ret_val(NULL != pcity, 0);
439 fc_assert_ret_val(NULL != pcity->server.adv, 0);
440 fc_assert_ret_val(NULL != pcity->server.adv->act_cache, 0);
441 fc_assert_ret_val(pcity->server.adv->act_cache_radius_sq
442 == city_map_radius_sq_get(pcity), 0);
443 fc_assert_ret_val(city_tile_index < city_map_tiles_from_city(pcity), 0);
444
445 return (pcity->server.adv->act_cache[city_tile_index]).rmextra[extra_index(pextra)];
446 }
447
448 /**************************************************************************
449 Update the memory allocated for AI city handling.
450 **************************************************************************/
adv_city_update(struct city * pcity)451 void adv_city_update(struct city *pcity)
452 {
453 int radius_sq = city_map_radius_sq_get(pcity);
454
455 fc_assert_ret(NULL != pcity);
456 fc_assert_ret(NULL != pcity->server.adv);
457
458 /* initialize act_cache if needed */
459 if (pcity->server.adv->act_cache == NULL
460 || pcity->server.adv->act_cache_radius_sq == -1
461 || pcity->server.adv->act_cache_radius_sq != radius_sq) {
462 pcity->server.adv->act_cache
463 = fc_realloc(pcity->server.adv->act_cache,
464 city_map_tiles(radius_sq)
465 * sizeof(*(pcity->server.adv->act_cache)));
466 /* initialize with 0 */
467 memset(pcity->server.adv->act_cache, 0,
468 city_map_tiles(radius_sq)
469 * sizeof(*(pcity->server.adv->act_cache)));
470 pcity->server.adv->act_cache_radius_sq = radius_sq;
471 }
472 }
473
474 /**************************************************************************
475 Allocate advisors related city data
476 **************************************************************************/
adv_city_alloc(struct city * pcity)477 void adv_city_alloc(struct city *pcity)
478 {
479 pcity->server.adv = fc_calloc(1, sizeof(*pcity->server.adv));
480
481 pcity->server.adv->act_cache = NULL;
482 pcity->server.adv->act_cache_radius_sq = -1;
483 /* allocate memory for pcity->ai->act_cache */
484 adv_city_update(pcity);
485 }
486
487 /**************************************************************************
488 Free advisors related city data
489 **************************************************************************/
adv_city_free(struct city * pcity)490 void adv_city_free(struct city *pcity)
491 {
492 fc_assert_ret(NULL != pcity);
493
494 if (pcity->server.adv) {
495 if (pcity->server.adv->act_cache) {
496 FC_FREE(pcity->server.adv->act_cache);
497 }
498 FC_FREE(pcity->server.adv);
499 }
500 }
501