Freeciv-3.2
Loading...
Searching...
No Matches
aitech.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#include <string.h>
19
20/* utility */
21#include "log.h"
22
23/* common */
24#include "game.h"
25#include "government.h"
26#include "player.h"
27#include "research.h"
28#include "tech.h"
29
30/* server */
31#include "plrhand.h"
32#include "srv_log.h"
33#include "techtools.h"
34
35/* server/advisors */
36#include "advdata.h"
37
38/* ai/default */
39#include "aitools.h"
40#include "daicity.h"
41#include "daidata.h"
42#include "daieffects.h"
43#include "dailog.h"
44#include "daiplayer.h"
45
46#include "aitech.h"
47
49 Tech_type_id choice; /* The id of the most needed tech */
50 adv_want want; /* Want of the most needed tech */
51 adv_want current_want; /* Want of the tech which is currently researched
52 * or is our current goal */
53};
54
55/**********************************************************************/
70static void dai_select_tech(struct ai_type *ait,
71 struct player *pplayer,
72 struct ai_tech_choice *choice,
73 struct ai_tech_choice *goal)
74{
75 struct research *presearch = research_get(pplayer);
77 int num_cities_nonzero = MAX(1, city_list_size(pplayer->cities));
78 int values[MAX(A_ARRAY_SIZE, A_UNSET + 1)];
80 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
82
83 memset(values, 0, sizeof(values));
84 values[A_UNSET] = -1;
85 values[A_NONE] = -1;
86 goal_values[A_UNSET] = -1;
87 goal_values[A_NONE] = -1;
88
89 /* If we are researching future techs, then simply continue with that
90 * when possible. */
91 if (is_future_tech(presearch->researching)) {
92 bool real_found = FALSE;
93
97 break;
98 }
100
101 if (!real_found) {
102 if (choice) {
103 choice->choice = presearch->researching;
104 choice->want = 1;
105 choice->current_want = 1;
106 }
107 if (goal) {
108 goal->choice = A_UNSET;
109 goal->want = 1;
110 goal->current_want = 1;
111 }
112 return;
113 }
114 }
115
116 /* Fill in values for the techs: want of the tech
117 * + average want of those we will discover en route */
121
122 /* We only want it if we haven't got it (so AI is human after all) */
123 if (steps > 0) {
124 values[i] += plr_data->tech_want[i];
127 values[k] += plr_data->tech_want[i] / steps;
128 }
130 }
131 }
133
134 /* Fill in the values for the tech goals */
138
139 if (steps == 0) {
140 /* Can't be set as a goal any more */
141 goal_values[i] = -1;
142 continue;
143 }
144
145 goal_values[i] = values[i];
148 goal_values[i] += values[k];
149 }
151
152 /* This is the best I could do. It still sometimes does freaky stuff
153 * like setting goal to Republic and learning Monarchy, but that's what
154 * it's supposed to be doing; it just looks strange. -- Syela */
155 goal_values[i] /= steps;
156 if (steps < 6) {
157 log_debug("%s: want = " ADV_WANT_PRINTF ", value = %d, goal_value = %d",
159 plr_data->tech_want[i],
160 values[i], goal_values[i]);
161 }
162 } else {
163 goal_values[i] = -1;
164 }
166
171 if (values[i] > values[newtech]
173 newtech = i;
174 }
177 newgoal = i;
178 }
179 }
181
182#ifdef REALLY_DEBUG_THIS
184 if (values[id] > 0
186 TECH_LOG(ait, LOG_DEBUG, pplayer, advance_by_number(id),
187 "turn end want: %d", values[id]);
188 }
190#endif /* REALLY_DEBUG_THIS */
191
192 if (choice) {
193 choice->choice = newtech;
194 choice->want = values[newtech] / num_cities_nonzero;
195 choice->current_want = (values[presearch->researching]
197 }
198
199 if (goal) {
200 goal->choice = newgoal;
202 goal->current_want = (goal_values[presearch->tech_goal]
204 log_debug("Goal->choice = %s, goal->want = " ADV_WANT_PRINTF ", goal_value = %d, "
205 "num_cities_nonzero = %d",
207 goal->want,
210 }
211
212 /* We can't have this, which will happen in the circumstance
213 * where all ai.tech_wants are negative */
214 if (choice && choice->choice == A_UNSET) {
215 choice->choice = presearch->researching;
216 }
217
218 return;
219}
220
221/**********************************************************************/
225static adv_want dai_tech_base_want(struct ai_type *ait, struct player *pplayer,
226 struct city *pcity, struct advance *padv)
227{
228 struct research *pres = research_get(pplayer);
231 struct adv_data *adv = adv_data_get(pplayer, NULL);
232 adv_want orig_want = dai_city_want(pplayer, pcity, adv, NULL);
234 bool world_knew = game.info.global_advances[tech];
236
238
239 final_want = dai_city_want(pplayer, pcity, adv, NULL);
240
244
245 return final_want - orig_want;
246}
247
248/**********************************************************************/
251static void dai_tech_effect_values(struct ai_type *ait, struct player *pplayer)
252{
253 /* TODO: Currently this duplicates code from daicity.c improvement effect
254 * evaluating almost verbose - refactor so that they can share code. */
255 struct adv_data *adv = adv_data_get(pplayer, NULL);
256 struct ai_plr *aip = def_ai_player_data(pplayer, ait);
257 int turns = 9999; /* TODO: Set to correct value */
258 int nplayers = normal_player_count();
259
260 /* Remove team members from the equation */
262 if (aplayer->team
263 && aplayer->team == pplayer->team
264 && aplayer != pplayer) {
265 nplayers--;
266 }
268
271 != TECH_KNOWN) {
272 struct universal source = { .kind = VUT_ADVANCE, .value.advance = padv };
273
274 city_list_iterate(pplayer->cities, pcity) {
275 adv_want v;
276 adv_want tech_want;
277 bool capital;
278 const struct req_context context = {
279 .player = pplayer,
280 .city = pcity,
281 };
282
283 v = dai_tech_base_want(ait, pplayer, pcity, padv);
284 capital = is_capital(pcity);
285
287 bool present = TRUE;
288 bool active = TRUE;
289
291 /* Check if all the requirements for the currently evaluated effect
292 * are met, except for having the tech that we are evaluating.
293 * TODO: Consider requirements that could be met later. */
294 if (VUT_ADVANCE == preq->source.kind
295 && preq->source.value.advance == padv) {
296 present = preq->present;
297 continue;
298 }
300 active = FALSE;
301 break; /* presence doesn't matter for inactive effects. */
302
303 }
305
306 if (active) {
307 adv_want v1;
308
309 v1 = dai_effect_value(pplayer, adv, pcity, capital,
310 turns, peffect, 1,
311 nplayers);
312
313 if (!present) {
314 /* Tech removes the effect */
315 v -= v1;
316 } else {
317 v += v1;
318 }
319 }
321
322 /* Same conversion factor as in want_tech_for_improvement_effect() */
323 tech_want = v * 14 / 8;
324
325 aip->tech_want[advance_index(padv)] += tech_want;
327 }
329}
330
331/**********************************************************************/
335void dai_manage_tech(struct ai_type *ait, struct player *pplayer)
336{
337 struct ai_tech_choice choice, goal;
338 struct research *research = research_get(pplayer);
339 /* Penalty for switching research */
340 /* FIXME: get real penalty with game.server.techpenalty and multiresearch */
342 penalty = MAX(penalty, 0);
343
344 /* Even when we let human to do the final decision, we keep our
345 * wants correctly calculated. Add effect values in */
346 dai_tech_effect_values(ait, pplayer);
347
348 /* If there are humans in our team, they will choose the techs */
350 if (!is_ai(aplayer)) {
351 return;
352 }
354
355 dai_select_tech(ait, pplayer, &choice, &goal);
356 if (choice.choice != research->researching) {
357 /* changing */
358 if (choice.want - choice.current_want > penalty
361 FALSE))) {
362 TECH_LOG(ait, LOG_DEBUG, pplayer, advance_by_number(choice.choice),
363 "new research, was %s, penalty was %d",
365 penalty);
366 choose_tech(research, choice.choice);
367 }
368 }
369
370 /* crossing my fingers on this one! -- Syela (seems to have worked!) */
371 /* It worked, in particular, because the value it sets (research->tech_goal)
372 * is practically never used, see the comment for ai_next_tech_goal */
373 if (goal.choice != research->tech_goal) {
374 log_debug("%s change goal from %s (want=" ADV_WANT_PRINTF
375 ") to %s (want=" ADV_WANT_PRINTF ")",
376 player_name(pplayer),
378 goal.current_want,
380 goal.want);
382 }
383}
384
385/**********************************************************************/
391 struct player *pplayer,
392 struct city *pcity,
393 const struct unit_type *att, int want)
394{
395 struct research *presearch = research_get(pplayer);
396 int best_avl_def = 0;
397 struct unit_type *best_avl = NULL;
399 struct advance *best_tech = A_NEVER;
400 struct unit_type *best_unit = NULL;
401 struct tile *ptile = city_tile(pcity);
402 int def_values[U_LAST];
403 int att_idx = utype_index(att);
404 int defbonus = 100
405 + get_unittype_bonus(pplayer, ptile, att, NULL, EFT_DEFEND_BONUS);
406
408 int mp_pct = deftype->cache.defense_mp_bonuses_pct[att_idx] + 100;
409 int scramble = deftype->cache.scramble_coeff[att_idx];
410 int div_bonus_pct = 100 + combat_bonus_against(att->bonuses, deftype,
412 + 100 * combat_bonus_against(att->bonuses, deftype,
414 /* Either the unit uses city defense bonus, or scrambles with its own one */
415 int def = deftype->defense_strength
417
419
420 if (can_city_build_unit_now(pcity, deftype)) {
421 if (def > best_avl_def) {
422 best_avl_def = def;
424 }
425 }
427
432 /* It would be better than current best. Consider researching tech */
433 const struct impr_type *building;
434 int cost = 0;
435 struct advance *itech = A_NEVER;
437
441 /* See if we want to invent this. */
444
445 if (cost == 0 || ucost < cost) {
446 cost = ucost;
447 itech = padv;
448 }
449 }
451
452 building = utype_needs_improvement(deftype, pcity);
453 if (building != NULL
454 && !can_player_build_improvement_direct(pplayer, building)) {
455 const struct req_context context = {
456 .player = pplayer,
457 .city = pcity,
458 .tile = city_tile(pcity),
459 .unittype = deftype,
460 .building = building,
461 };
462
465
466 if (VUT_ADVANCE == preq->source.kind && preq->present) {
467 int iimprtech = advance_number(preq->source.value.advance);
469 iimprtech);
470
471 if (imprcost < cost || cost == 0) {
472 /* If we already have the primary tech (cost == 0),
473 * or the building's tech is cheaper,
474 * go for the building's required tech. */
475 itech = preq->source.value.advance;
476 cost = imprcost;
477 }
478 } else if (!dai_can_requirement_be_met_in_city(preq, pplayer,
479 pcity)) {
481 }
482 }
484 }
485
489 best_cost = cost;
491 }
492 }
494
495 if (A_NEVER != best_tech) {
496 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
497
498 /* Crank up chosen tech want */
499 if (best_avl != NULL
501 /* We already have almost as good unit suitable for defending against this attacker */
502 want /= 2;
503 }
504
505 plr_data->tech_want[advance_index(best_tech)] += want;
506 TECH_LOG(ait, LOG_DEBUG, pplayer, best_tech,
507 "+ %d for %s by role",
508 want,
510 }
511
512 return best_avl;
513}
514
515/**********************************************************************/
521struct unit_type *dai_wants_role_unit(struct ai_type *ait, struct player *pplayer,
522 struct city *pcity, int role, int want)
523{
524 struct research *presearch = research_get(pplayer);
525 int i, n;
527 struct advance *best_tech = A_NEVER;
528 struct unit_type *best_unit = NULL;
529 struct unit_type *build_unit = NULL;
530
532 for (i = n - 1; i >= 0; i--) {
533 struct unit_type *iunit = get_role_unit(role, i);
534
535 if (can_city_build_unit_now(pcity, iunit)) {
537 break;
538 } else if (can_city_build_unit_later(pcity, iunit)) {
539 const struct impr_type *building;
540 struct advance *itech = A_NEVER;
541 int cost = 0;
542
546 /* See if we want to invent this. */
549
550 if (cost == 0 || ucost < cost) {
551 cost = ucost;
552 itech = padv;
553 }
554 }
556
557 building = utype_needs_improvement(iunit, pcity);
558 if (building != NULL
559 && !can_player_build_improvement_direct(pplayer, building)) {
561 if (VUT_ADVANCE == preq->source.kind && preq->present) {
562 int iimprtech = advance_number(preq->source.value.advance);
563
565 iimprtech)) {
567 iimprtech);
568
569 if (imprcost < cost || cost == 0) {
570 /* If we already have the primary tech (cost == 0),
571 * or the building's tech is cheaper,
572 * go for the building's required tech. */
573 itech = preq->source.value.advance;
574 cost = imprcost;
575 }
576 }
577 }
579 }
580
581 if (cost < best_cost && itech != A_NEVER
584 best_cost = cost;
586 }
587 }
588 }
589
590 if (A_NEVER != best_tech) {
591 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
592
593 /* Crank up chosen tech want */
594 if (build_unit != NULL) {
595 /* We already have a role unit of this kind */
596 want /= 2;
597 }
598 plr_data->tech_want[advance_index(best_tech)] += want;
599 TECH_LOG(ait, LOG_DEBUG, pplayer, best_tech,
600 "+ %d for %s by role",
601 want,
603 }
604
605 return build_unit;
606}
607
608/**********************************************************************/
611void dai_clear_tech_wants(struct ai_type *ait, struct player *pplayer)
612{
613 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
614
616 plr_data->tech_want[i] = 0;
618}
struct adv_data * adv_data_get(struct player *pplayer, bool *caller_closes)
Definition advdata.c:605
static adv_want dai_tech_base_want(struct ai_type *ait, struct player *pplayer, struct city *pcity, struct advance *padv)
Definition aitech.c:225
void dai_clear_tech_wants(struct ai_type *ait, struct player *pplayer)
Definition aitech.c:611
void dai_manage_tech(struct ai_type *ait, struct player *pplayer)
Definition aitech.c:335
static void dai_select_tech(struct ai_type *ait, struct player *pplayer, struct ai_tech_choice *choice, struct ai_tech_choice *goal)
Definition aitech.c:70
struct unit_type * dai_wants_defender_against(struct ai_type *ait, struct player *pplayer, struct city *pcity, const struct unit_type *att, int want)
Definition aitech.c:390
static void dai_tech_effect_values(struct ai_type *ait, struct player *pplayer)
Definition aitech.c:251
struct unit_type * dai_wants_role_unit(struct ai_type *ait, struct player *pplayer, struct city *pcity, int role, int want)
Definition aitech.c:521
#define n
Definition astring.c:77
bool can_city_build_unit_later(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:965
bool is_capital(const struct city *pcity)
Definition city.c:1571
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:945
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define city_list_iterate_end
Definition city.h:510
int combat_bonus_against(const struct combat_bonus_list *list, const struct unit_type *enemy, enum combat_bonus_type type)
Definition combat.c:1000
char * incite_cost
Definition comments.c:74
adv_want dai_city_want(struct player *pplayer, struct city *acity, struct adv_data *adv, struct impr_type *pimprove)
Definition daicity.c:1424
bool dai_can_requirement_be_met_in_city(const struct requirement *preq, const struct player *pplayer, const struct city *pcity)
Definition daieffects.c:782
adv_want dai_effect_value(struct player *pplayer, const struct adv_data *adv, const struct city *pcity, const bool capital, int turns, const struct effect *peffect, const int c, const int nplayers)
Definition daieffects.c:138
#define TECH_LOG(ait, loglevel, pplayer, padvance, msg,...)
Definition dailog.h:36
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition daiplayer.h:54
const struct impr_type * utype_needs_improvement(const struct unit_type *putype, const struct city *pcity)
Definition daiunit.c:2892
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 cost
Definition dialogs_g.h:74
struct effect_list * get_req_source_effects(const struct universal *psource)
Definition effects.c:153
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:1035
#define effect_list_iterate_end
Definition effects.h:406
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:404
float adv_want
Definition fc_types.h:1355
int Tech_type_id
Definition fc_types.h:380
@ RPT_CERTAIN
Definition fc_types.h:704
@ RPT_POSSIBLE
Definition fc_types.h:703
#define ADV_WANT_PRINTF
Definition fc_types.h:1356
struct civ_game game
Definition game.c:62
static GtkWidget * source
Definition gotodlg.c:58
bool can_player_build_improvement_direct(const struct player *p, const struct impr_type *pimprove)
#define log_debug(message,...)
Definition log.h:115
@ LOG_DEBUG
Definition log.h:34
const char * player_name(const struct player *pplayer)
Definition player.c:895
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define is_ai(plr)
Definition player.h:230
int normal_player_count(void)
Definition plrhand.c:3200
bool is_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
int research_goal_unknown_techs(const struct research *presearch, Tech_type_id goal)
Definition research.c:750
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:668
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Definition research.c:807
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:637
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:240
int research_goal_bulbs_required(const struct research *presearch, Tech_type_id goal)
Definition research.c:772
int research_total_bulbs_required(const struct research *presearch, Tech_type_id tech, bool loss_value)
Definition research.c:868
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:693
#define research_players_iterate(_presearch, _pplayer)
Definition research.h:166
#define research_players_iterate_end
Definition research.h:170
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
Tech_type_id choice
Definition aitech.c:49
adv_want want
Definition aitech.c:50
adv_want current_want
Definition aitech.c:51
Definition ai.h:50
Definition city.h:320
struct tile * tile
Definition city.h:322
struct packet_game_info info
Definition game.h:89
struct requirement_vector reqs
Definition improvement.h:58
bool global_advances[A_LAST]
struct city_list * cities
Definition player.h:279
struct team * team
Definition player.h:259
const struct impr_type * building
const struct player * player
Tech_type_id researching
Definition research.h:52
Tech_type_id tech_goal
Definition research.h:83
int bulbs_researched
Definition research.h:53
int free_bulbs
Definition research.h:67
Definition tile.h:50
enum universals_n kind
Definition fc_types.h:903
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_ARRAY_SIZE
Definition tech.h:47
#define advance_index_iterate_max(_start, _index, _max)
Definition tech.h:252
#define A_NEVER
Definition tech.h:51
#define advance_index_iterate_end
Definition tech.h:248
#define advance_index_iterate_max_end
Definition tech.h:258
static Tech_type_id advance_count(void)
Definition tech.h:170
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:275
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:276
#define advance_index_iterate(_start, _index)
Definition tech.h:244
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1074
void choose_tech(struct research *research, Tech_type_id tech)
Definition techtools.c:1004
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
int num_role_units(int role)
Definition unittype.c:2203
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1578
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
#define unit_tech_reqs_iterate_end
Definition unittype.h:878
#define unit_tech_reqs_iterate(_utype_, _p)
Definition unittype.h:872
#define unit_type_iterate(_p)
Definition unittype.h:852
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:859