Freeciv-3.2
Loading...
Searching...
No Matches
infracache.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/* 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 */
40
41static adv_want adv_calc_cultivate(const struct city *pcity,
42 const struct tile *ptile);
43static adv_want adv_calc_plant(const struct city *pcity,
44 const struct tile *ptile);
45static adv_want adv_calc_transform(const struct city *pcity,
46 const struct tile *ptile);
47static adv_want adv_calc_extra(const struct city *pcity,
48 const struct tile *ptile,
49 const struct extra_type *pextra);
50static adv_want adv_calc_rmextra(const struct city *pcity,
51 const struct tile *ptile,
52 const struct extra_type *pextra);
53
54/**********************************************************************/
62static adv_want adv_calc_cultivate(const struct city *pcity,
63 const struct tile *ptile)
64{
67
68 fc_assert_ret_val(ptile != NULL, -1);
69
71 new_terrain = old_terrain->cultivate_result;
72
74 struct tile *vtile;
75
77 /* Not a valid activity. */
78 return -1;
79 }
80 /* Irrigation would change the terrain type, clearing conflicting
81 * extras in the process. Calculate the benefit of doing so. */
82 vtile = tile_virtual_new(ptile);
83
85 goodness = city_tile_value(pcity, vtile, 0, 0);
87
88 return goodness;
89 } else {
90 return -1;
91 }
92}
93
94/**********************************************************************/
102static adv_want adv_calc_plant(const struct city *pcity,
103 const struct tile *ptile)
104{
107
108 fc_assert_ret_val(ptile != NULL, -1);
109
110 old_terrain = tile_terrain(ptile);
111 new_terrain = old_terrain->plant_result;
112
114 struct tile *vtile;
115
117 /* Not a valid activity. */
118 return -1;
119 }
120 /* Mining would change the terrain type, clearing conflicting
121 * extras in the process. Calculate the benefit of doing so. */
122 vtile = tile_virtual_new(ptile);
123
125 goodness = city_tile_value(pcity, vtile, 0, 0);
127
128 return goodness;
129 } else {
130 return -1;
131 }
132}
133
134/**********************************************************************/
142static adv_want adv_calc_transform(const struct city *pcity,
143 const struct tile *ptile)
144{
146 struct tile *vtile;
148 const struct civ_map *nmap = &(wld.map);
149
150 fc_assert_ret_val(ptile != NULL, -1);
151
152 old_terrain = tile_terrain(ptile);
153 new_terrain = old_terrain->transform_result;
154
156 return -1;
157 }
158
160 /* Can't do this terrain conversion here. */
161 return -1;
162 }
163
165 return -1;
166 }
167
168 vtile = tile_virtual_new(ptile);
170 goodness = city_tile_value(pcity, vtile, 0, 0);
172
173 return goodness;
174}
175
176/**********************************************************************/
188static adv_want adv_calc_extra(const struct city *pcity,
189 const struct tile *ptile,
190 const struct extra_type *pextra)
191{
192 adv_want goodness = -1;
193
194 fc_assert_ret_val(ptile != NULL, -1);
195
196 if (player_can_build_extra(pextra, city_owner(pcity), ptile)) {
197 struct tile *vtile = tile_virtual_new(ptile);
198
199 tile_add_extra(vtile, pextra);
200
203 && !can_extras_coexist(pextra, cextra)) {
205 }
207
208 goodness = city_tile_value(pcity, vtile, 0, 0);
210 }
211
212 return goodness;
213}
214
215/**********************************************************************/
223static adv_want adv_calc_rmextra(const struct city *pcity,
224 const struct tile *ptile,
225 const struct extra_type *pextra)
226{
227 adv_want goodness = -1;
228
229 fc_assert_ret_val(ptile != NULL, -1);
230
231 if (player_can_remove_extra(pextra, city_owner(pcity), ptile)) {
232 struct tile *vtile = tile_virtual_new(ptile);
233
234 tile_remove_extra(vtile, pextra);
235
236 goodness = city_tile_value(pcity, vtile, 0, 0);
238 }
239
240 return goodness;
241}
242
243/**********************************************************************/
251{
252 const struct civ_map *nmap = &(wld.map);
253
254 city_list_iterate(pplayer->cities, pcity) {
255 struct tile *pcenter = city_tile(pcity);
256 int radius_sq = city_map_radius_sq_get(pcity);
257
261 -1);
264
265 city_tile_iterate_index(nmap, radius_sq, pcenter, ptile, cindex) {
267 adv_calc_plant(pcity, ptile));
269 adv_calc_cultivate(pcity, ptile));
271 adv_calc_transform(pcity, ptile));
272
273 /* road_bonus() is handled dynamically later; it takes into
274 * account settlers that have already been assigned to building
275 * roads this turn. */
276 extra_type_iterate(pextra) {
277 /* We have no use for extra value, if workers cannot be assigned
278 * to build it, so don't use time to calculate values otherwise */
279 if (pextra->buildable
281 adv_city_worker_extra_set(pcity, cindex, pextra,
282 adv_calc_extra(pcity, ptile, pextra));
283 } else {
284 adv_city_worker_extra_set(pcity, cindex, pextra, 0);
285 }
286 if (tile_has_extra(ptile, pextra) && is_extra_removed_by_worker_action(pextra)) {
287 adv_city_worker_rmextra_set(pcity, cindex, pextra,
288 adv_calc_rmextra(pcity, ptile, pextra));
289 } else {
290 adv_city_worker_rmextra_set(pcity, cindex, pextra, 0);
291 }
295}
296
297/**********************************************************************/
302adv_want city_tile_value(const struct city *pcity, const struct tile *ptile,
303 int foodneed, int prodneed)
304{
305 int food = city_tile_output_now(pcity, ptile, O_FOOD);
306 int shield = city_tile_output_now(pcity, ptile, O_SHIELD);
307 int trade = city_tile_output_now(pcity, ptile, O_TRADE);
308 adv_want value = 0;
309
310 /* Each food, trade, and shield gets a certain weighting. We also benefit
311 * tiles that have at least one of an item - this promotes balance and
312 * also accounts for INC_TILE effects. */
313 value += food * FOOD_WEIGHTING;
314 if (food > 0) {
315 value += FOOD_WEIGHTING / 2;
316 }
317 value += shield * SHIELD_WEIGHTING;
318 if (shield > 0) {
319 value += SHIELD_WEIGHTING / 2;
320 }
321 value += trade * TRADE_WEIGHTING;
322 if (trade > 0) {
323 value += TRADE_WEIGHTING / 2;
324 }
325
326 return value;
327}
328
329/**********************************************************************/
334 enum unit_activity act_id, adv_want value)
335{
336 if (pcity->server.adv->act_cache_radius_sq
337 != city_map_radius_sq_get(pcity)) {
338 log_debug("update activity cache for %s: radius_sq changed from "
339 "%d to %d", city_name_get(pcity),
342 adv_city_update(pcity);
343 }
344
345 fc_assert_ret(NULL != pcity);
346 fc_assert_ret(NULL != pcity->server.adv);
349 == city_map_radius_sq_get(pcity));
351
352 (pcity->server.adv->act_cache[city_tile_index]).act[act_id] = value;
353}
354
355/**********************************************************************/
360 int city_tile_index,
361 enum unit_activity act_id)
362{
363 fc_assert_ret_val(NULL != pcity, 0);
364 fc_assert_ret_val(NULL != pcity->server.adv, 0);
367 == city_map_radius_sq_get(pcity), 0);
369
370 return (pcity->server.adv->act_cache[city_tile_index]).act[act_id];
371}
372
373/**********************************************************************/
378 const struct extra_type *pextra, int value)
379{
380 if (pcity->server.adv->act_cache_radius_sq
381 != city_map_radius_sq_get(pcity)) {
382 log_debug("update activity cache for %s: radius_sq changed from "
383 "%d to %d", city_name_get(pcity),
386 adv_city_update(pcity);
387 }
388
389 fc_assert_ret(NULL != pcity);
390 fc_assert_ret(NULL != pcity->server.adv);
393 == city_map_radius_sq_get(pcity));
395
396 (pcity->server.adv->act_cache[city_tile_index]).extra[extra_index(pextra)] = value;
397}
398
399/**********************************************************************/
404 const struct extra_type *pextra, int value)
405{
406 if (pcity->server.adv->act_cache_radius_sq
407 != city_map_radius_sq_get(pcity)) {
408 log_debug("update activity cache for %s: radius_sq changed from "
409 "%d to %d", city_name_get(pcity),
412 adv_city_update(pcity);
413 }
414
415 fc_assert_ret(NULL != pcity);
416 fc_assert_ret(NULL != pcity->server.adv);
419 == city_map_radius_sq_get(pcity));
421
422 (pcity->server.adv->act_cache[city_tile_index]).rmextra[extra_index(pextra)] = value;
423}
424
425/**********************************************************************/
429int adv_city_worker_extra_get(const struct city *pcity, int city_tile_index,
430 const struct extra_type *pextra)
431{
432 fc_assert_ret_val(NULL != pcity, 0);
433 fc_assert_ret_val(NULL != pcity->server.adv, 0);
436 == city_map_radius_sq_get(pcity), 0);
438
439 return (pcity->server.adv->act_cache[city_tile_index]).extra[extra_index(pextra)];
440}
441
442/**********************************************************************/
447 const struct extra_type *pextra)
448{
449 fc_assert_ret_val(NULL != pcity, 0);
450 fc_assert_ret_val(NULL != pcity->server.adv, 0);
453 == city_map_radius_sq_get(pcity), 0);
455
456 return (pcity->server.adv->act_cache[city_tile_index]).rmextra[extra_index(pextra)];
457}
458
459/**********************************************************************/
462void adv_city_update(struct city *pcity)
463{
464 int radius_sq = city_map_radius_sq_get(pcity);
465
466 fc_assert_ret(NULL != pcity);
467 fc_assert_ret(NULL != pcity->server.adv);
468
469 /* initialize act_cache if needed */
470 if (pcity->server.adv->act_cache == NULL
471 || pcity->server.adv->act_cache_radius_sq == -1
472 || pcity->server.adv->act_cache_radius_sq != radius_sq) {
473 pcity->server.adv->act_cache
474 = fc_realloc(pcity->server.adv->act_cache,
475 city_map_tiles(radius_sq)
476 * sizeof(*(pcity->server.adv->act_cache)));
477 /* initialize with 0 */
478 memset(pcity->server.adv->act_cache, 0,
479 city_map_tiles(radius_sq)
480 * sizeof(*(pcity->server.adv->act_cache)));
481 pcity->server.adv->act_cache_radius_sq = radius_sq;
482 }
483}
484
485/**********************************************************************/
488void adv_city_alloc(struct city *pcity)
489{
490 pcity->server.adv = fc_calloc(1, sizeof(*pcity->server.adv));
491
492 pcity->server.adv->act_cache = NULL;
493 pcity->server.adv->act_cache_radius_sq = -1;
494 /* Allocate memory for pcity->ai->act_cache */
495 adv_city_update(pcity);
496}
497
498/**********************************************************************/
501void adv_city_free(struct city *pcity)
502{
503 fc_assert_ret(NULL != pcity);
504
505 if (pcity->server.adv) {
506 if (pcity->server.adv->act_cache) {
507 FC_FREE(pcity->server.adv->act_cache);
508 }
509 FC_FREE(pcity->server.adv);
510 }
511}
#define action_id_get_activity(act_id)
Definition actions.h:701
#define TRADE_WEIGHTING
Definition advbuilding.h:21
#define FOOD_WEIGHTING
Definition advbuilding.h:19
#define SHIELD_WEIGHTING
Definition advbuilding.h:20
#define as_transform_action_iterate_end
#define as_transform_action_iterate(_act_)
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
int city_tile_output_now(const struct city *pcity, const struct tile *ptile, Output_type_id otype)
Definition city.c:1384
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
int city_map_tiles(int city_radius_sq)
Definition city.c:171
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define city_tile_iterate_index(_nmap, _radius_sq, _city_tile, _tile, _index)
Definition city.h:201
#define city_tile_iterate_index_end
Definition city.h:209
#define city_owner(_pcity_)
Definition city.h:563
#define city_list_iterate_end
Definition city.h:510
#define city_map_iterate_end
Definition city.h:177
#define city_map_iterate(_radius_sq, _index, _x, _y)
Definition city.h:173
#define city_map_tiles_from_city(_pcity)
Definition city.h:127
char * incite_cost
Definition comments.c:75
bool is_extra_removed_by_worker_action(const struct extra_type *pextra)
Definition extras.c:1045
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:1032
bool player_can_build_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:468
bool can_extras_coexist(const struct extra_type *pextra1, const struct extra_type *pextra2)
Definition extras.c:1003
bool player_can_remove_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Definition extras.c:591
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define extra_index(_e_)
Definition extras.h:183
float adv_want
Definition fc_types.h:1354
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
@ O_SHIELD
Definition fc_types.h:101
@ O_FOOD
Definition fc_types.h:101
@ O_TRADE
Definition fc_types.h:101
struct world wld
Definition game.c:63
static adv_want adv_calc_transform(const struct city *pcity, const struct tile *ptile)
Definition infracache.c:142
adv_want adv_city_worker_act_get(const struct city *pcity, int city_tile_index, enum unit_activity act_id)
Definition infracache.c:359
void adv_city_free(struct city *pcity)
Definition infracache.c:501
static adv_want adv_calc_extra(const struct city *pcity, const struct tile *ptile, const struct extra_type *pextra)
Definition infracache.c:188
static adv_want adv_calc_rmextra(const struct city *pcity, const struct tile *ptile, const struct extra_type *pextra)
Definition infracache.c:223
void adv_city_worker_extra_set(struct city *pcity, int city_tile_index, const struct extra_type *pextra, int value)
Definition infracache.c:377
void adv_city_update(struct city *pcity)
Definition infracache.c:462
void adv_city_worker_act_set(struct city *pcity, int city_tile_index, enum unit_activity act_id, adv_want value)
Definition infracache.c:333
int adv_city_worker_extra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:429
void initialize_infrastructure_cache(struct player *pplayer)
Definition infracache.c:250
void adv_city_worker_rmextra_set(struct city *pcity, int city_tile_index, const struct extra_type *pextra, int value)
Definition infracache.c:403
int adv_city_worker_rmextra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:446
static adv_want adv_calc_cultivate(const struct city *pcity, const struct tile *ptile)
Definition infracache.c:62
static adv_want adv_calc_plant(const struct city *pcity, const struct tile *ptile)
Definition infracache.c:102
void adv_city_alloc(struct city *pcity)
Definition infracache.c:488
adv_want city_tile_value(const struct city *pcity, const struct tile *ptile, int foodneed, int prodneed)
Definition infracache.c:302
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
bool terrain_surroundings_allow_change(const struct civ_map *nmap, const struct tile *ptile, const struct terrain *pterrain)
Definition map.c:742
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_realloc(ptr, sz)
Definition mem.h:36
int act_cache_radius_sq
Definition infracache.h:25
struct worker_activity_cache * act_cache
Definition infracache.h:24
Definition city.h:320
struct adv_city * adv
Definition city.h:452
struct city::@17::@19 server
struct city_list * cities
Definition player.h:279
Definition tile.h:50
adv_want extra[MAX_EXTRA_TYPES]
Definition infracache.c:37
adv_want rmextra[MAX_EXTRA_TYPES]
Definition infracache.c:38
adv_want act[ACTIVITY_LAST]
Definition infracache.c:36
struct civ_map map
#define T_NONE
Definition terrain.h:56
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1033
void tile_remove_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:965
void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:496
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:981
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:110
#define tile_has_extra(ptile, pextra)
Definition tile.h:147