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
164 if (!city_can_work_tile(pcity, ptile)) {
165 return;
166 }
167
168 orig_value = city_tile_value(pcity, ptile, 0, 0);
169
170 if (tile_worked(ptile) == pcity
171 && orig_value < state->worst_worked) {
172 state->worst_worked = orig_value;
175 }
176
178 bool consider = TRUE;
179 bool possible = FALSE;
180 enum extra_cause cause;
182 struct extra_type *tgt = NULL;
183
184 /* Do not request activities that already are under way. */
185 unit_list_iterate(ptile->units, punit) {
186 if (unit_owner(punit) == pplayer
189 consider = FALSE;
190 break;
191 }
193
194 if (!consider) {
195 continue;
196 }
197
200
201 unit_list_iterate(units, punit) {
202 if (cause != EC_NONE) {
203 tgt = next_extra_for_tile(ptile, cause, pplayer, punit);
204 } else if (rmcause != ERM_NONE) {
205 tgt = prev_extra_in_tile(ptile, rmcause, pplayer, punit);
206 }
207
210 punit, unit_home(punit), ptile,
211 TRUE,
212 ptile, tgt))) {
213 possible = TRUE;
214 break;
215 }
217
218 if (possible) {
219 int value = adv_city_worker_act_get(pcity, cindex,
221
222 if (tile_worked(ptile) == pcity) {
223 if ((value - orig_value) * TWMP > worked->want) {
224 worked->want = TWMP * (value - orig_value);
225 worked->ptile = ptile;
226 worked->act = action_id_get_activity(act);
227 worked->tgt = NULL;
229 unit_list_iterate(units, punit) {
233 ptile,
234 TRUE,
235 ptile, tgt))) {
236 state->wants[utype_index(unit_type_get(punit))] += worked->want;
237 }
239 }
240 }
241 if (value > state->old_worst_worked) {
242 /* After improvement it would not be the worst */
244 } else {
245 state->worst_worked = value;
246 }
247 } else {
248 if (value > orig_value && value > state->uw_max) {
249 state->uw_max = value;
250 state->uw_max_base = value;
251 unworked->want = TWMP * (value - orig_value);
252 unworked->ptile = ptile;
254 unworked->tgt = NULL;
256 unit_list_iterate(units, punit) {
260 ptile,
261 TRUE,
262 ptile, tgt))) {
263 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
264 }
266 }
267 }
268 }
269 }
271
272 extra_type_iterate(tgt) {
273 struct action *paction = NULL;
274 bool removing = tile_has_extra(ptile, tgt);
275
276 unit_list_iterate(units, punit) {
277 if (removing) {
283 punit,
284 unit_home(punit), ptile,
285 TRUE,
286 ptile, tgt))) {
288 break;
289 }
291 } else {
297 punit,
298 unit_home(punit), ptile,
299 TRUE,
300 ptile, tgt))) {
302 break;
303 }
305 }
307
308 if (paction != NULL) {
309 adv_want base_value;
310 int value;
311 adv_want extra;
312 bool consider = TRUE;
313 struct road_type *proad;
314
315 /* Do not request activities that already are under way. */
316 unit_list_iterate(ptile->units, punit) {
317 if (unit_owner(punit) == pplayer
320 consider = FALSE;
321 break;
322 }
324
325 if (!consider) {
326 continue;
327 }
328
329 proad = extra_road_get(tgt);
330
331 if (removing) {
332 base_value = adv_city_worker_rmextra_get(pcity, cindex, tgt);
333 } else {
334 base_value = adv_city_worker_extra_get(pcity, cindex, tgt);
335 }
336
338 int old_move_cost;
339 int mc_multiplier = 1;
340 int mc_divisor = 1;
341
342 /* Here 'old' means actually 'without the evaluated': In case of
343 * removal activity it's the value after the removal. */
344 old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE;
345
347 struct road_type *pold = extra_road_get(poe);
348
349 if (tile_has_extra(ptile, poe) && poe != tgt) {
351 && pold->move_cost < old_move_cost) {
352 old_move_cost = pold->move_cost;
353 }
354 }
356
357 if (proad->move_cost < old_move_cost) {
358 if (proad->move_cost >= terrain_control.move_fragments) {
359 mc_divisor = proad->move_cost / terrain_control.move_fragments;
360 } else {
361 if (proad->move_cost == 0) {
362 mc_multiplier = 2;
363 } else {
364 mc_multiplier = 1 - proad->move_cost;
365 }
367 }
368 }
369
370 extra = adv_settlers_road_bonus(&(wld.map), ptile, proad)
372
373 if (removing) {
374 extra = -extra;
375 }
376 } else {
377 extra = 0;
378 }
379
380 value = base_value + extra;
381
382 if (tile_worked(ptile) == pcity) {
383 if ((value - orig_value) * TWMP > worked->want) {
384 worked->want = TWMP * (value - orig_value);
385 worked->ptile = ptile;
387 worked->tgt = tgt;
389 unit_list_iterate(units, punit) {
391 break);
393 paction->id,
394 punit, unit_home(punit), ptile,
395 TRUE,
396 ptile, tgt))) {
397 state->wants[utype_index(unit_type_get(punit))] += worked->want;
398 }
400 }
401 }
402 if (value > state->old_worst_worked) {
403 /* After improvement it would not be the worst */
405 } else {
406 state->worst_worked = value;
407 }
408 } else {
409 if (value > orig_value && value > state->uw_max) {
410 state->uw_max = value;
411 state->uw_max_base = base_value;
412 unworked->want = TWMP * (value - orig_value);
413 unworked->ptile = ptile;
415 unworked->tgt = tgt;
417 unit_list_iterate(units, punit) {
419 break);
421 paction->id,
422 punit, unit_home(punit), ptile,
423 TRUE,
424 ptile, tgt))) {
425 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
426 }
428 }
429 }
430 }
431 }
433
435 /* Would still be worst worked even if we improved *it*. */
436 state->old_worst_worked = state->worst_worked;
437 }
438}
439
440/**********************************************************************/
444 struct player *pplayer, struct city *pcity,
445 struct worker_task *task,
447{
448 struct worker_task *selected;
449 struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
450 struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
451 struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0, .worst_worked = FC_INFINITY,
452 .orig_worst_worked = 0, .old_worst_worked = FC_INFINITY };
453 struct unit_list *units = NULL;
454 const struct civ_map *nmap = &(wld.map);
455
456 switch (limit) {
458 units = texai_player_units(pplayer);
459 state.wants = NULL;
460 break;
462 units = unit_list_new();
464 if (can_city_build_unit_now(pcity, ptype)) {
465 unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
466 }
468 state.wants = texai_city_data(ait, pcity)->unit_wants;
469 break;
470 }
471
473 ptile, cindex) {
474 texai_tile_worker_task_select(pplayer, pcity, ptile, cindex, units,
475 &worked, &unworked, &state, limit);
477
478 if (worked.ptile == NULL
479 || (state.old_worst_worked < state.uw_max
480 && (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)
481 || (state.uw_max - state.uw_max_base * TWMP > worked.want)) {
482 /* It's better to improve best yet unworked tile and take it to use after that,
483 than to improve already worked tile. OR it's more important to
484 improve road connectivity outside worked tiles than improve worked tiles */
485 selected = &unworked;
486 } else {
487 selected = &worked;
488 }
489
491 unit_list_iterate(units, punit) {
494 unit_list_destroy(units);
495 }
496
497 if (selected->ptile != NULL) {
498 struct extra_type *target = NULL;
499
500 if (selected->tgt == NULL) {
501 enum extra_cause cause = activity_to_extra_cause(selected->act);
502
503 if (cause != EC_NONE) {
504 target = next_extra_for_tile(selected->ptile, cause, pplayer, NULL);
505 } else {
507
508 if (rmcause != ERM_NONE) {
509 target = prev_extra_in_tile(selected->ptile, rmcause, pplayer, NULL);
510 }
511 }
512 } else {
513 target = selected->tgt;
514 }
515
516 task->ptile = selected->ptile;
517 task->act = selected->act;
518 task->tgt = target;
519 task->want = selected->want;
520
521 return TRUE;
522 }
523
524 return FALSE;
525}
526
527/**********************************************************************/
531{
532 struct texai_worker_task_req *data = (struct texai_worker_task_req *)req->data;
533 struct city *pcity;
534
535 pcity = game_city_by_number(data->city_id);
536
537 if (pcity != NULL && city_owner(pcity) == req->plr) {
538 /* City has not been lost meanwhile */
539 struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
540
541 if (ptask == NULL) {
542 ptask = fc_malloc(sizeof(struct worker_task));
545 }
546
547 log_debug("%s storing req for act %d at (%d,%d)",
548 pcity->name, data->task.act, TILE_XY(data->task.ptile));
549 ptask->ptile = data->task.ptile;
550 ptask->act = data->task.act;
551 ptask->tgt = data->task.tgt;
552 ptask->want = data->task.want;
553
554 /* Send info to observers */
556 }
557
558 free(data);
559}
560
561/**********************************************************************/
564void texai_city_alloc(struct ai_type *ait, struct city *pcity)
565{
566 struct texai_city *city_data = fc_calloc(1, sizeof(struct texai_city));
567
568 city_data->defai.building_wait = BUILDING_WAIT_MINIMUM;
569 adv_init_choice(&(city_data->defai.choice));
570
571 city_set_ai_data(pcity, ait, city_data);
572}
573
574/**********************************************************************/
577void texai_city_free(struct ai_type *ait, struct city *pcity)
578{
579 struct texai_city *city_data = texai_city_data(ait, pcity);
580
581 if (city_data != NULL) {
582 adv_deinit_choice(&(city_data->defai.choice));
583 city_set_ai_data(pcity, ait, NULL);
585 }
586}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5823
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1860
struct act_prob action_speculate_unit_on_tile(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:5676
static struct action * action_by_number(action_id act_id)
Definition actions.h:633
#define action_get_activity(_pact_)
Definition actions.h:697
#define action_id_get_activity(act_id)
Definition actions.h:699
#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:3605
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:136
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1447
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:945
#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:3586
char * incite_cost
Definition comments.c:74
#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:1355
#define EC_NONE
Definition fc_types.h:1114
#define ERM_NONE
Definition fc_types.h:1137
@ O_FOOD
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:375
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:443
void texai_city_alloc(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:564
void texai_city_free(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:577
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:530
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:1620
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1725
#define unit_owner(_pu)
Definition unit.h:389
#define unit_home(_pu_)
Definition unit.h:387
#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:852
#define unit_type_iterate_end
Definition unittype.h:859
void worker_task_init(struct worker_task *ptask)
Definition workertask.c:31