Freeciv-3.2
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 "autosettlers.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
109 texai_city_worker_task_select(ait, pplayer, pcity, &task, TWTL_BUILDABLE_UNITS);
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) {
284 punit,
285 unit_home(punit), ptile,
286 TRUE,
287 ptile, tgt))) {
289 break;
290 }
292 } else {
298 punit,
299 unit_home(punit), ptile,
300 TRUE,
301 ptile, tgt))) {
303 break;
304 }
306 }
308
309 if (paction != NULL) {
310 adv_want base_value;
311 int value;
312 adv_want extra;
313 bool consider = TRUE;
314 struct road_type *proad;
315
316 /* Do not request activities that already are under way. */
317 unit_list_iterate(ptile->units, punit) {
318 if (unit_owner(punit) == pplayer
321 consider = FALSE;
322 break;
323 }
325
326 if (!consider) {
327 continue;
328 }
329
330 proad = extra_road_get(tgt);
331
332 if (removing) {
333 base_value = adv_city_worker_rmextra_get(pcity, cindex, tgt);
334 } else {
335 base_value = adv_city_worker_extra_get(pcity, cindex, tgt);
336 }
337
339 int old_move_cost;
340 int mc_multiplier = 1;
341 int mc_divisor = 1;
342
343 /* Here 'old' means actually 'without the evaluated': In case of
344 * removal activity it's the value after the removal. */
345 old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE;
346
348 struct road_type *pold = extra_road_get(poe);
349
350 if (tile_has_extra(ptile, poe) && poe != tgt) {
352 && pold->move_cost < old_move_cost) {
353 old_move_cost = pold->move_cost;
354 }
355 }
357
358 if (proad->move_cost < old_move_cost) {
359 if (proad->move_cost >= terrain_control.move_fragments) {
360 mc_divisor = proad->move_cost / terrain_control.move_fragments;
361 } else {
362 if (proad->move_cost == 0) {
363 mc_multiplier = 2;
364 } else {
365 mc_multiplier = 1 - proad->move_cost;
366 }
368 }
369 }
370
371 extra = adv_settlers_road_bonus(&(wld.map), ptile, proad)
373
374 if (removing) {
375 extra = -extra;
376 }
377 } else {
378 extra = 0;
379 }
380
381 value = base_value + extra;
382
383 if (tile_worked(ptile) == pcity) {
384 if ((value - orig_value) * TWMP > worked->want) {
385 worked->want = TWMP * (value - orig_value);
386 worked->ptile = ptile;
388 worked->tgt = tgt;
390 unit_list_iterate(units, punit) {
392 break);
394 nmap, paction->id,
395 punit, unit_home(punit), ptile,
396 TRUE,
397 ptile, tgt))) {
398 state->wants[utype_index(unit_type_get(punit))] += worked->want;
399 }
401 }
402 }
403 if (value > state->old_worst_worked) {
404 /* After improvement it would not be the worst */
406 } else {
407 state->worst_worked = value;
408 }
409 } else {
410 if (value > orig_value && value > state->uw_max) {
411 state->uw_max = value;
412 state->uw_max_base = base_value;
413 unworked->want = TWMP * (value - orig_value);
414 unworked->ptile = ptile;
416 unworked->tgt = tgt;
418 unit_list_iterate(units, punit) {
420 break);
422 nmap, paction->id,
423 punit, unit_home(punit), ptile,
424 TRUE,
425 ptile, tgt))) {
426 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
427 }
429 }
430 }
431 }
432 }
434
436 /* Would still be worst worked even if we improved *it*. */
437 state->old_worst_worked = state->worst_worked;
438 }
439}
440
441/**********************************************************************/
445 struct player *pplayer, struct city *pcity,
446 struct worker_task *task,
448{
449 struct worker_task *selected;
450 struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
451 struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
452 struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0, .worst_worked = FC_INFINITY,
453 .orig_worst_worked = 0, .old_worst_worked = FC_INFINITY };
454 struct unit_list *units = NULL;
455 const struct civ_map *nmap = &(wld.map);
456
457 switch (limit) {
459 units = texai_player_units(pplayer);
460 state.wants = NULL;
461 break;
463 units = unit_list_new();
465 if (can_city_build_unit_now(nmap, pcity, ptype)) {
466 unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
467 }
469 state.wants = texai_city_data(ait, pcity)->unit_wants;
470 break;
471 }
472
474 ptile, cindex) {
475 texai_tile_worker_task_select(pplayer, pcity, ptile, cindex, units,
476 &worked, &unworked, &state, limit);
478
479 if (worked.ptile == NULL
480 || (state.old_worst_worked < state.uw_max
481 && (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)
482 || (state.uw_max - state.uw_max_base * TWMP > worked.want)) {
483 /* It's better to improve best yet unworked tile and take it to use after that,
484 than to improve already worked tile. OR it's more important to
485 improve road connectivity outside worked tiles than improve worked tiles */
486 selected = &unworked;
487 } else {
488 selected = &worked;
489 }
490
492 unit_list_iterate(units, punit) {
495 unit_list_destroy(units);
496 }
497
498 if (selected->ptile != NULL) {
499 struct extra_type *target = NULL;
500
501 if (selected->tgt == NULL) {
502 enum extra_cause cause = activity_to_extra_cause(selected->act);
503
504 if (cause != EC_NONE) {
505 target = next_extra_for_tile(selected->ptile, cause, pplayer, NULL);
506 } else {
508
509 if (rmcause != ERM_NONE) {
510 target = prev_extra_in_tile(selected->ptile, rmcause, pplayer, NULL);
511 }
512 }
513 } else {
514 target = selected->tgt;
515 }
516
517 task->ptile = selected->ptile;
518 task->act = selected->act;
519 task->tgt = target;
520 task->want = selected->want;
521
522 return TRUE;
523 }
524
525 return FALSE;
526}
527
528/**********************************************************************/
532{
533 struct texai_worker_task_req *data = (struct texai_worker_task_req *)req->data;
534 struct city *pcity;
535
536 pcity = game_city_by_number(data->city_id);
537
538 if (pcity != NULL && city_owner(pcity) == req->plr) {
539 /* City has not been lost meanwhile */
540 struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
541
542 if (ptask == NULL) {
543 ptask = fc_malloc(sizeof(struct worker_task));
546 }
547
548 log_debug("%s storing req for act %d at (%d,%d)",
549 pcity->name, data->task.act, TILE_XY(data->task.ptile));
550 ptask->ptile = data->task.ptile;
551 ptask->act = data->task.act;
552 ptask->tgt = data->task.tgt;
553 ptask->want = data->task.want;
554
555 /* Send info to observers */
557 }
558
559 free(data);
560}
561
562/**********************************************************************/
565void texai_city_alloc(struct ai_type *ait, struct city *pcity)
566{
567 struct texai_city *city_data = fc_calloc(1, sizeof(struct texai_city));
568
569 city_data->defai.building_wait = BUILDING_WAIT_MINIMUM;
570 adv_init_choice(&(city_data->defai.choice));
571
572 city_set_ai_data(pcity, ait, city_data);
573}
574
575/**********************************************************************/
578void texai_city_free(struct ai_type *ait, struct city *pcity)
579{
580 struct texai_city *city_data = texai_city_data(ait, pcity);
581
582 if (city_data != NULL) {
583 adv_deinit_choice(&(city_data->defai.choice));
584 city_set_ai_data(pcity, ait, NULL);
586 }
587}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5821
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:5675
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1869
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
#define action_get_activity(_pact_)
Definition actions.h:699
#define action_id_get_activity(act_id)
Definition actions.h:701
#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:605
adv_want adv_settlers_road_bonus(const struct civ_map *nmap, struct tile *ptile, struct road_type *proad)
#define as_transform_action_iterate_end
#define as_rmextra_action_iterate(_act_)
#define as_rmextra_action_iterate_end
#define as_extra_action_iterate_end
#define as_extra_action_iterate(_act_)
#define as_transform_action_iterate(_act_)
void city_set_ai_data(struct city *pcity, const struct ai_type *ai, void *data)
Definition city.c:3617
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:564
#define city_tile_iterate_index(_nmap, _radius_sq, _city_tile, _tile, _index)
Definition city.h:201
#define city_owner(_pcity_)
Definition city.h:563
#define city_tile_iterate_end
Definition city.h:238
void package_and_send_worker_tasks(struct city *pcity)
Definition citytools.c:3615
char * incite_cost
Definition comments.c:75
#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 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:765
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:790
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1076
bool is_extra_caused_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1056
bool is_extra_removed_by_action(const struct extra_type *pextra, const struct action *paction)
Definition extras.c:1066
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1097
#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:1354
#define EC_NONE
Definition fc_types.h:1113
#define ERM_NONE
Definition fc_types.h:1136
@ O_FOOD
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:372
struct world wld
Definition game.c:63
struct city * game_city_by_number(int id)
Definition game.c:107
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:359
int adv_city_worker_extra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:429
int adv_city_worker_rmextra_get(const struct city *pcity, int city_tile_index, const struct extra_type *pextra)
Definition infracache.c:446
adv_want city_tile_value(const struct city *pcity, const struct tile *ptile, int foodneed, int prodneed)
Definition infracache.c:302
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
struct terrain_misc terrain_control
Definition map.c:69
#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:499
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
int * cities
Definition advdata.h:96
struct adv_data::@91 stats
Definition ai.h:50
Definition city.h:320
struct worker_task_list * task_reqs
Definition city.h:412
int id
Definition city.h:326
char * name
Definition city.h:321
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:157
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:444
void texai_city_alloc(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:565
void texai_city_free(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:578
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:531
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:114
#define tile_terrain(_tile)
Definition tile.h:110
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1624
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1729
#define unit_owner(_pu)
Definition unit.h:396
#define unit_home(_pu_)
Definition unit.h:394
#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:190
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
#define unit_type_iterate(_p)
Definition unittype.h:855
#define unit_type_iterate_end
Definition unittype.h:862
void worker_task_init(struct worker_task *ptask)
Definition workertask.c:31