Freeciv-3.3
Loading...
Searching...
No Matches
texaicity.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 "log.h"
20
21/* common */
22#include "city.h"
23#include "game.h"
24#include "map.h"
25#include "movement.h"
26#include "tile.h"
27#include "unit.h"
28#include "workertask.h"
29
30/* server */
31#include "citytools.h"
32
33/* server/advisors */
34#include "advbuilding.h"
35#include "advdata.h"
36#include "autoworkers.h"
37#include "infracache.h"
38
39/* ai/default */
40#include "daidata.h"
41
42/* ai/tex */
43#include "texaimsg.h"
44#include "texaiplayer.h"
45
46#include "texaicity.h"
47
48/* Task Want Multiplier */
49#define TWMP 100
50
56
61
62static bool texai_city_worker_task_select(struct ai_type *ait,
63 struct player *pplayer,
64 struct city *pcity,
65 struct worker_task *task,
67
68/**********************************************************************/
73 struct player *pplayer, struct city *pcity)
74{
75 struct worker_task task;
76
77 if (texai_city_worker_task_select(ait, pplayer, pcity, &task, TWTL_CURRENT_UNITS)) {
78 struct texai_worker_task_req *data = fc_malloc(sizeof(*data));
79
80 data->city_id = pcity->id;
81 data->task.ptile = task.ptile;
82 data->task.act = task.act;
83 data->task.tgt = task.tgt;
84 data->task.want = task.want;
85
87 }
88}
89
90/**********************************************************************/
94 struct player *pplayer, struct city *pcity)
95{
96 struct worker_task task;
97 struct texai_city *cdata = texai_city_data(ait, pcity);
98 int *wants = cdata->unit_wants;
99 int maxwant = 0;
100 struct unit_type *type = NULL;
102 struct ai_plr *dai = dai_plr_data_get(ait, pplayer, NULL);
103 struct adv_data *adv = adv_data_get(pplayer, NULL);
104
106 wants[utype_index(ptype)] = 0;
108
110
112 int twant = wants[utype_index(ptype)];
113
114 twant -= 20 * ptype->pop_cost;
115 twant -= ptype->build_cost;
116 twant -= ptype->upkeep[O_FOOD] * FOOD_WEIGHTING / 2;
117
118 /* Massage our desire based on available statistics to prevent
119 * overflooding with worker type units if they come cheap in
120 * the ruleset */
121 if (place >= 0) {
122 twant /= MAX(1, dai->stats.workers[place] / (adv->stats.cities[place] + 1));
123 twant -= dai->stats.workers[place];
124 } else {
125 /* TODO: Handle Oceans with cities sensibly */
126 }
127
128 twant = MAX(twant, 0);
129
130 if (twant > maxwant) {
131 maxwant = twant;
132 type = ptype;
133 }
135
136 cdata->defai.worker_want = maxwant / 70;
137 cdata->defai.worker_type = type;
138}
139
141{
142 int uw_max_base; /* Value for the city working the tile */
143 int uw_max; /* With road connectivity bonus */
147 int *wants;
148};
149
150/**********************************************************************/
153static void texai_tile_worker_task_select(struct player *pplayer,
154 struct city *pcity, struct tile *ptile,
155 int cindex, struct unit_list *units,
156 struct worker_task *worked,
157 struct worker_task *unworked,
158 struct texai_tile_state *state,
160{
161 int orig_value;
163 const struct civ_map *nmap = &(wld.map);
164
165 if (!city_can_work_tile(pcity, ptile)) {
166 return;
167 }
168
169 orig_value = city_tile_value(pcity, ptile, 0, 0);
170
171 if (tile_worked(ptile) == pcity
172 && orig_value < state->worst_worked) {
173 state->worst_worked = orig_value;
176 }
177
179 bool consider = TRUE;
180 bool possible = FALSE;
181 enum extra_cause cause;
183 struct extra_type *tgt = NULL;
184
185 /* Do not request activities that already are under way. */
186 unit_list_iterate(ptile->units, punit) {
187 if (unit_owner(punit) == pplayer
190 consider = FALSE;
191 break;
192 }
194
195 if (!consider) {
196 continue;
197 }
198
201
202 unit_list_iterate(units, punit) {
203 if (cause != EC_NONE) {
204 tgt = next_extra_for_tile(ptile, cause, pplayer, punit);
205 } else if (rmcause != ERM_NONE) {
206 tgt = prev_extra_in_tile(ptile, rmcause, pplayer, punit);
207 }
208
211 punit, unit_home(punit), ptile,
212 TRUE,
213 ptile, tgt))) {
214 possible = TRUE;
215 break;
216 }
218
219 if (possible) {
220 int value = adv_city_worker_act_get(pcity, cindex,
222
223 if (tile_worked(ptile) == pcity) {
224 if ((value - orig_value) * TWMP > worked->want) {
225 worked->want = TWMP * (value - orig_value);
226 worked->ptile = ptile;
227 worked->act = action_id_get_activity(act);
228 worked->tgt = NULL;
230 unit_list_iterate(units, punit) {
234 ptile,
235 TRUE,
236 ptile, tgt))) {
237 state->wants[utype_index(unit_type_get(punit))] += worked->want;
238 }
240 }
241 }
242 if (value > state->old_worst_worked) {
243 /* After improvement it would not be the worst */
245 } else {
246 state->worst_worked = value;
247 }
248 } else {
249 if (value > orig_value && value > state->uw_max) {
250 state->uw_max = value;
251 state->uw_max_base = value;
252 unworked->want = TWMP * (value - orig_value);
253 unworked->ptile = ptile;
255 unworked->tgt = NULL;
257 unit_list_iterate(units, punit) {
261 ptile,
262 TRUE,
263 ptile, tgt))) {
264 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
265 }
267 }
268 }
269 }
270 }
272
273 extra_type_iterate(tgt) {
274 struct action *paction = NULL;
275 bool removing = tile_has_extra(ptile, tgt);
276
277 unit_list_iterate(units, punit) {
278 if (removing) {
281
285 punit,
286 unit_home(punit), ptile,
287 TRUE,
288 ptile, tgt))) {
290 break;
291 }
293 } else {
296
300 punit,
301 unit_home(punit), ptile,
302 TRUE,
303 ptile, tgt))) {
305 break;
306 }
308 }
310
311 if (paction != NULL) {
312 adv_want base_value;
313 int value;
314 adv_want extra;
315 bool consider = TRUE;
316 struct road_type *proad;
317
318 /* Do not request activities that already are under way. */
319 unit_list_iterate(ptile->units, punit) {
320 if (unit_owner(punit) == pplayer
323 consider = FALSE;
324 break;
325 }
327
328 if (!consider) {
329 continue;
330 }
331
332 proad = extra_road_get(tgt);
333
334 if (removing) {
335 base_value = adv_city_worker_rmextra_get(pcity, cindex, tgt);
336 } else {
337 base_value = adv_city_worker_extra_get(pcity, cindex, tgt);
338 }
339
341 int old_move_cost;
342 int mc_multiplier = 1;
343 int mc_divisor = 1;
344
345 /* Here 'old' means actually 'without the evaluated': In case of
346 * removal activity it's the value after the removal. */
347 old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE;
348
350 struct road_type *pold = extra_road_get(poe);
351
352 if (tile_has_extra(ptile, poe) && poe != tgt) {
354 && pold->move_cost < old_move_cost) {
355 old_move_cost = pold->move_cost;
356 }
357 }
359
360 if (proad->move_cost < old_move_cost) {
361 if (proad->move_cost >= terrain_control.move_fragments) {
362 mc_divisor = proad->move_cost / terrain_control.move_fragments;
363 } else {
364 if (proad->move_cost == 0) {
365 mc_multiplier = 2;
366 } else {
367 mc_multiplier = 1 - proad->move_cost;
368 }
370 }
371 }
372
373 extra = adv_workers_road_bonus(&(wld.map), ptile, proad)
375
376 if (removing) {
377 extra = -extra;
378 }
379 } else {
380 extra = 0;
381 }
382
383 value = base_value + extra;
384
385 if (tile_worked(ptile) == pcity) {
386 if ((value - orig_value) * TWMP > worked->want) {
387 worked->want = TWMP * (value - orig_value);
388 worked->ptile = ptile;
390 worked->tgt = tgt;
392 unit_list_iterate(units, punit) {
394 break);
396 nmap, paction->id,
397 punit, unit_home(punit), ptile,
398 TRUE,
399 ptile, tgt))) {
400 state->wants[utype_index(unit_type_get(punit))] += worked->want;
401 }
403 }
404 }
405 if (value > state->old_worst_worked) {
406 /* After improvement it would not be the worst */
408 } else {
409 state->worst_worked = value;
410 }
411 } else {
412 if (value > orig_value && value > state->uw_max) {
413 state->uw_max = value;
414 state->uw_max_base = base_value;
415 unworked->want = TWMP * (value - orig_value);
416 unworked->ptile = ptile;
418 unworked->tgt = tgt;
420 unit_list_iterate(units, punit) {
422 break);
424 nmap, paction->id,
425 punit, unit_home(punit), ptile,
426 TRUE,
427 ptile, tgt))) {
428 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
429 }
431 }
432 }
433 }
434 }
436
438 /* Would still be worst worked even if we improved *it*. */
439 state->old_worst_worked = state->worst_worked;
440 }
441}
442
443/**********************************************************************/
447 struct player *pplayer, struct city *pcity,
448 struct worker_task *task,
450{
451 struct worker_task *selected;
452 struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
453 struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
454 struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0, .worst_worked = FC_INFINITY,
455 .orig_worst_worked = 0, .old_worst_worked = FC_INFINITY };
456 struct unit_list *units = NULL;
457 const struct civ_map *nmap = &(wld.map);
458
459 switch (limit) {
461 units = texai_player_units(pplayer);
462 state.wants = NULL;
463 break;
465 units = unit_list_new();
468 unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
469 }
471 state.wants = texai_city_data(ait, pcity)->unit_wants;
472 break;
473 }
474
476 ptile, cindex) {
477 texai_tile_worker_task_select(pplayer, pcity, ptile, cindex, units,
478 &worked, &unworked, &state, limit);
480
481 if (worked.ptile == NULL
482 || (state.old_worst_worked < state.uw_max
483 && (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)
484 || (state.uw_max - state.uw_max_base * TWMP > worked.want)) {
485 /* It's better to improve best yet unworked tile and take it to use after that,
486 than to improve already worked tile. OR it's more important to
487 improve road connectivity outside worked tiles than improve worked tiles */
488 selected = &unworked;
489 } else {
490 selected = &worked;
491 }
492
494 unit_list_iterate(units, punit) {
497 unit_list_destroy(units);
498 }
499
500 if (selected->ptile != NULL) {
501 struct extra_type *target = NULL;
502
503 if (selected->tgt == NULL) {
504 enum extra_cause cause = activity_to_extra_cause(selected->act);
505
506 if (cause != EC_NONE) {
507 target = next_extra_for_tile(selected->ptile, cause, pplayer, NULL);
508 } else {
510
511 if (rmcause != ERM_NONE) {
512 target = prev_extra_in_tile(selected->ptile, rmcause, pplayer, NULL);
513 }
514 }
515 } else {
516 target = selected->tgt;
517 }
518
519 task->ptile = selected->ptile;
520 task->act = selected->act;
521 task->tgt = target;
522 task->want = selected->want;
523
524 return TRUE;
525 }
526
527 return FALSE;
528}
529
530/**********************************************************************/
534{
535 struct texai_worker_task_req *data = (struct texai_worker_task_req *)req->data;
536 struct city *pcity;
537
539
540 if (pcity != NULL && city_owner(pcity) == req->plr) {
541 /* City has not been lost meanwhile */
542 struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
543
544 if (ptask == NULL) {
545 ptask = fc_malloc(sizeof(struct worker_task));
548 }
549
550 log_debug("%s storing req for act %d at (%d,%d)",
551 pcity->name, data->task.act, TILE_XY(data->task.ptile));
552 ptask->ptile = data->task.ptile;
553 ptask->act = data->task.act;
554 ptask->tgt = data->task.tgt;
555 ptask->want = data->task.want;
556
557 /* Send info to observers */
559 }
560
561 free(data);
562}
563
564/**********************************************************************/
567void texai_city_alloc(struct ai_type *ait, struct city *pcity)
568{
569 struct texai_city *city_data = fc_calloc(1, sizeof(struct texai_city));
570
571 city_data->defai.building_wait = BUILDING_WAIT_MINIMUM;
572 adv_init_choice(&(city_data->defai.choice));
573
575}
576
577/**********************************************************************/
580void texai_city_free(struct ai_type *ait, struct city *pcity)
581{
583
584 if (city_data != NULL) {
585 adv_deinit_choice(&(city_data->defai.choice));
588 }
589}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5091
struct act_prob action_speculate_unit_on_tile(const struct civ_map *nmap, action_id act_id, const struct unit *actor, const struct city *actor_home, const struct tile *actor_tile, bool omniscient_cheat, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4945
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1108
static struct action * action_by_number(action_id act_id)
Definition actions.h:396
#define action_get_activity(_pact_)
Definition actions.h:460
#define action_id_get_activity(act_id)
Definition actions.h:462
#define FOOD_WEIGHTING
Definition advbuilding.h:19
void adv_deinit_choice(struct adv_choice *choice)
Definition advchoice.c:46
void adv_init_choice(struct adv_choice *choice)
Definition advchoice.c:31
struct adv_data * adv_data_get(struct player *pplayer, bool *caller_closes)
Definition advdata.c:606
adv_want adv_workers_road_bonus(const struct civ_map *nmap, struct tile *ptile, struct road_type *proad)
#define aw_extra_action_iterate(_act_)
Definition autoworkers.h:84
#define aw_transform_action_iterate(_act_)
Definition autoworkers.h:74
#define aw_rmextra_action_iterate_end
Definition autoworkers.h:98
#define aw_extra_action_iterate_end
Definition autoworkers.h:88
#define aw_transform_action_iterate_end
Definition autoworkers.h:78
#define aw_rmextra_action_iterate(_act_)
Definition autoworkers.h:94
void city_set_ai_data(struct city *pcity, const struct ai_type *ai, void *data)
Definition city.c:3642
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
bool can_city_build_unit_now(const struct civ_map *nmap, const struct city *pcity, const struct unit_type *punittype)
Definition city.c:947
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1456
#define city_tile(_pcity_)
Definition city.h:561
#define city_tile_iterate_index(_nmap, _radius_sq, _city_tile, _tile, _index)
Definition city.h:198
#define city_owner(_pcity_)
Definition city.h:560
#define city_tile_iterate_end
Definition city.h:235
void package_and_send_worker_tasks(struct city *pcity)
Definition citytools.c:3624
char * incite_cost
Definition comments.c:76
#define BUILDING_WAIT_MINIMUM
Definition daicity.h:39
struct ai_plr * dai_plr_data_get(struct ai_type *ait, struct player *pplayer, bool *caller_closes)
Definition daidata.c:308
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
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:804
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1090
bool is_extra_caused_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1070
bool is_extra_removed_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1080
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1111
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define extra_road_get(_e_)
Definition extras.h:191
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
float adv_want
Definition fc_types.h:1063
#define EC_NONE
Definition fc_types.h:821
#define ERM_NONE
Definition fc_types.h:844
@ O_FOOD
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:231
struct world wld
Definition game.c:62
struct city * game_city_by_number(int id)
Definition game.c:106
GType type
Definition repodlgs.c:1313
adv_want adv_city_worker_act_get(const struct city *pcity, int city_tile_index, enum unit_activity act_id)
Definition infracache.c:360
int adv_city_worker_extra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:430
int adv_city_worker_rmextra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:447
adv_want city_tile_value(const struct city *pcity, const struct tile *ptile, int foodneed, int prodneed)
Definition infracache.c:303
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
struct terrain_misc terrain_control
Definition map.c:68
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
#define SINGLE_MOVE
Definition movement.h:26
bool road_provides_move_bonus(const struct road_type *proad)
Definition road.c:505
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
int * cities
Definition advdata.h:96
struct adv_data::@94 stats
Definition ai.h:50
Definition city.h:317
int unit_wants[U_LAST]
Definition texaicity.h:25
void * data
Definition texaimsg.h:65
struct player * plr
Definition texaimsg.h:64
struct worker_task task
Definition texaicity.c:54
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
enum unit_activity activity
Definition unit.h:159
int id
Definition unit.h:147
enum unit_activity act
Definition workertask.h:23
struct tile * ptile
Definition workertask.h:22
struct extra_type * tgt
Definition workertask.h:24
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
texai_worker_task_limitation
Definition texaicity.c:57
@ TWTL_BUILDABLE_UNITS
Definition texaicity.c:59
@ TWTL_CURRENT_UNITS
Definition texaicity.c:58
#define TWMP
Definition texaicity.c:49
static void texai_tile_worker_task_select(struct player *pplayer, struct city *pcity, struct tile *ptile, int cindex, struct unit_list *units, struct worker_task *worked, struct worker_task *unworked, struct texai_tile_state *state, enum texai_worker_task_limitation limit)
Definition texaicity.c:153
static bool texai_city_worker_task_select(struct ai_type *ait, struct player *pplayer, struct city *pcity, struct worker_task *task, enum texai_worker_task_limitation limit)
Definition texaicity.c:446
void texai_city_alloc(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:567
void texai_city_free(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:580
void texai_city_worker_requests_create(struct ai_type *ait, struct player *pplayer, struct city *pcity)
Definition texaicity.c:72
void texai_city_worker_wants(struct ai_type *ait, struct player *pplayer, struct city *pcity)
Definition texaicity.c:93
void texai_req_worker_task_rcv(struct texai_req *req)
Definition texaicity.c:533
static struct texai_city * texai_city_data(struct ai_type *ait, const struct city *pcity)
Definition texaicity.h:37
void texai_send_req(enum texaireqtype type, struct player *pplayer, void *data)
Definition texaimsg.c:48
struct unit_list * texai_player_units(struct player *pplayer)
#define tile_worked(_tile)
Definition tile.h:115
#define tile_terrain(_tile)
Definition tile.h:111
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1661
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1766
#define unit_owner(_pu)
Definition unit.h:403
#define unit_home(_pu_)
Definition unit.h:401
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:196
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
#define unit_type_iterate(_p)
Definition unittype.h:862
#define unit_type_iterate_end
Definition unittype.h:869
void worker_task_init(struct worker_task *ptask)
Definition workertask.c:31