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
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) {
280
284 punit,
285 unit_home(punit), ptile,
286 TRUE,
287 ptile, tgt))) {
289 break;
290 }
292 } else {
295
299 punit,
300 unit_home(punit), ptile,
301 TRUE,
302 ptile, tgt))) {
304 break;
305 }
307 }
309
310 if (paction != NULL) {
311 adv_want base_value;
312 int value;
313 adv_want extra;
314 bool consider = TRUE;
315 struct road_type *proad;
316
317 /* Do not request activities that already are under way. */
318 unit_list_iterate(ptile->units, punit) {
319 if (unit_owner(punit) == pplayer
322 consider = FALSE;
323 break;
324 }
326
327 if (!consider) {
328 continue;
329 }
330
331 proad = extra_road_get(tgt);
332
333 if (removing) {
334 base_value = adv_city_worker_rmextra_get(pcity, cindex, tgt);
335 } else {
336 base_value = adv_city_worker_extra_get(pcity, cindex, tgt);
337 }
338
340 int old_move_cost;
341 int mc_multiplier = 1;
342 int mc_divisor = 1;
343
344 /* Here 'old' means actually 'without the evaluated': In case of
345 * removal activity it's the value after the removal. */
346 old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE;
347
349 struct road_type *pold = extra_road_get(poe);
350
351 if (tile_has_extra(ptile, poe) && poe != tgt) {
353 && pold->move_cost < old_move_cost) {
354 old_move_cost = pold->move_cost;
355 }
356 }
358
359 if (proad->move_cost < old_move_cost) {
360 if (proad->move_cost >= terrain_control.move_fragments) {
361 mc_divisor = proad->move_cost / terrain_control.move_fragments;
362 } else {
363 if (proad->move_cost == 0) {
364 mc_multiplier = 2;
365 } else {
366 mc_multiplier = 1 - proad->move_cost;
367 }
369 }
370 }
371
372 extra = adv_workers_road_bonus(&(wld.map), ptile, proad)
374
375 if (removing) {
376 extra = -extra;
377 }
378 } else {
379 extra = 0;
380 }
381
382 value = base_value + extra;
383
384 if (tile_worked(ptile) == pcity) {
385 if ((value - orig_value) * TWMP > worked->want) {
386 worked->want = TWMP * (value - orig_value);
387 worked->ptile = ptile;
389 worked->tgt = tgt;
391 unit_list_iterate(units, punit) {
393 break);
395 paction->id,
396 punit, unit_home(punit), ptile,
397 TRUE,
398 ptile, tgt))) {
399 state->wants[utype_index(unit_type_get(punit))] += worked->want;
400 }
402 }
403 }
404 if (value > state->old_worst_worked) {
405 /* After improvement it would not be the worst */
407 } else {
408 state->worst_worked = value;
409 }
410 } else {
411 if (value > orig_value && value > state->uw_max) {
412 state->uw_max = value;
413 state->uw_max_base = base_value;
414 unworked->want = TWMP * (value - orig_value);
415 unworked->ptile = ptile;
417 unworked->tgt = tgt;
419 unit_list_iterate(units, punit) {
421 break);
423 paction->id,
424 punit, unit_home(punit), ptile,
425 TRUE,
426 ptile, tgt))) {
427 state->wants[utype_index(unit_type_get(punit))] += unworked->want;
428 }
430 }
431 }
432 }
433 }
435
437 /* Would still be worst worked even if we improved *it*. */
438 state->old_worst_worked = state->worst_worked;
439 }
440}
441
442/**********************************************************************/
446 struct player *pplayer, struct city *pcity,
447 struct worker_task *task,
449{
450 struct worker_task *selected;
451 struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
452 struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
453 struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0, .worst_worked = FC_INFINITY,
454 .orig_worst_worked = 0, .old_worst_worked = FC_INFINITY };
455 struct unit_list *units = NULL;
456 const struct civ_map *nmap = &(wld.map);
457
458 switch (limit) {
460 units = texai_player_units(pplayer);
461 state.wants = NULL;
462 break;
464 units = unit_list_new();
466 if (can_city_build_unit_now(pcity, ptype)) {
467 unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
468 }
470 state.wants = texai_city_data(ait, pcity)->unit_wants;
471 break;
472 }
473
475 ptile, cindex) {
476 texai_tile_worker_task_select(pplayer, pcity, ptile, cindex, units,
477 &worked, &unworked, &state, limit);
479
480 if (worked.ptile == NULL
481 || (state.old_worst_worked < state.uw_max
482 && (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)
483 || (state.uw_max - state.uw_max_base * TWMP > worked.want)) {
484 /* It's better to improve best yet unworked tile and take it to use after that,
485 than to improve already worked tile. OR it's more important to
486 improve road connectivity outside worked tiles than improve worked tiles */
487 selected = &unworked;
488 } else {
489 selected = &worked;
490 }
491
493 unit_list_iterate(units, punit) {
496 unit_list_destroy(units);
497 }
498
499 if (selected->ptile != NULL) {
500 struct extra_type *target = NULL;
501
502 if (selected->tgt == NULL) {
503 enum extra_cause cause = activity_to_extra_cause(selected->act);
504
505 if (cause != EC_NONE) {
506 target = next_extra_for_tile(selected->ptile, cause, pplayer, NULL);
507 } else {
509
510 if (rmcause != ERM_NONE) {
511 target = prev_extra_in_tile(selected->ptile, rmcause, pplayer, NULL);
512 }
513 }
514 } else {
515 target = selected->tgt;
516 }
517
518 task->ptile = selected->ptile;
519 task->act = selected->act;
520 task->tgt = target;
521 task->want = selected->want;
522
523 return TRUE;
524 }
525
526 return FALSE;
527}
528
529/**********************************************************************/
533{
534 struct texai_worker_task_req *data = (struct texai_worker_task_req *)req->data;
535 struct city *pcity;
536
537 pcity = game_city_by_number(data->city_id);
538
539 if (pcity != NULL && city_owner(pcity) == req->plr) {
540 /* City has not been lost meanwhile */
541 struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
542
543 if (ptask == NULL) {
544 ptask = fc_malloc(sizeof(struct worker_task));
547 }
548
549 log_debug("%s storing req for act %d at (%d,%d)",
550 pcity->name, data->task.act, TILE_XY(data->task.ptile));
551 ptask->ptile = data->task.ptile;
552 ptask->act = data->task.act;
553 ptask->tgt = data->task.tgt;
554 ptask->want = data->task.want;
555
556 /* Send info to observers */
558 }
559
560 free(data);
561}
562
563/**********************************************************************/
566void texai_city_alloc(struct ai_type *ait, struct city *pcity)
567{
568 struct texai_city *city_data = fc_calloc(1, sizeof(struct texai_city));
569
570 city_data->defai.building_wait = BUILDING_WAIT_MINIMUM;
571 adv_init_choice(&(city_data->defai.choice));
572
573 city_set_ai_data(pcity, ait, city_data);
574}
575
576/**********************************************************************/
579void texai_city_free(struct ai_type *ait, struct city *pcity)
580{
581 struct texai_city *city_data = texai_city_data(ait, pcity);
582
583 if (city_data != NULL) {
584 adv_deinit_choice(&(city_data->defai.choice));
585 city_set_ai_data(pcity, ait, NULL);
587 }
588}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5044
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1083
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:4897
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
#define action_get_activity(_pact_)
Definition actions.h:454
#define action_id_get_activity(act_id)
Definition actions.h:456
#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:604
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:3613
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1452
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:948
#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:3599
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: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:1335
#define EC_NONE
Definition fc_types.h:1093
#define ERM_NONE
Definition fc_types.h:1116
@ O_FOOD
Definition fc_types.h:101
signed short Continent_id
Definition fc_types.h:376
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:187
#define log_debug(message,...)
Definition log.h:115
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::@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:159
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:445
void texai_city_alloc(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:566
void texai_city_free(struct ai_type *ait, struct city *pcity)
Definition texaicity.c:579
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:532
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:1662
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1767
#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:859
#define unit_type_iterate_end
Definition unittype.h:866
void worker_task_init(struct worker_task *ptask)
Definition workertask.c:31