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