Freeciv-3.3
Loading...
Searching...
No Matches
daitech.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 "daicity.h"
40#include "daidata.h"
41#include "daieffects.h"
42#include "dailog.h"
43#include "daiplayer.h"
44#include "daiunit.h"
45
46#include "daitech.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 const struct civ_map *nmap,
392 struct player *pplayer,
393 struct city *pcity,
394 const struct unit_type *att, int want)
395{
396 struct research *presearch = research_get(pplayer);
397 int best_avl_def = 0;
398 struct unit_type *best_avl = NULL;
400 struct advance *best_tech = A_NEVER;
401 struct unit_type *best_unit = NULL;
402 struct tile *ptile = city_tile(pcity);
403 int def_values[U_LAST];
404 int att_idx = utype_index(att);
405 int defbonus = 100
406 + get_unittype_bonus(pplayer, ptile, att, NULL, EFT_DEFEND_BONUS);
407
409 int mp_pct = deftype->cache.defense_mp_bonuses_pct[att_idx] + 100;
410 int scramble = deftype->cache.scramble_coeff[att_idx];
411 int div_bonus_pct = 100 + combat_bonus_against(att->bonuses, deftype,
413 + 100 * combat_bonus_against(att->bonuses, deftype,
415 /* Either the unit uses city defense bonus, or scrambles with its own one */
416 int def = deftype->defense_strength
418
420
422 if (def > best_avl_def) {
423 best_avl_def = def;
425 }
426 }
428
433 /* It would be better than current best. Consider researching tech */
434 const struct impr_type *building;
435 int cost = 0;
436 struct advance *itech = A_NEVER;
438
442 /* See if we want to invent this. */
445
446 if (cost == 0 || ucost < cost) {
447 cost = ucost;
448 itech = padv;
449 }
450 }
452
454 if (building != NULL
455 && !can_player_build_improvement_direct(pplayer, building)) {
456 const struct req_context context = {
457 .player = pplayer,
458 .city = pcity,
459 .tile = city_tile(pcity),
460 .unittype = deftype,
461 .building = building,
462 };
463
466
467 if (VUT_ADVANCE == preq->source.kind && preq->present) {
468 int iimprtech = advance_number(preq->source.value.advance);
470 iimprtech);
471
472 if (imprcost < cost || cost == 0) {
473 /* If we already have the primary tech (cost == 0),
474 * or the building's tech is cheaper,
475 * go for the building's required tech. */
476 itech = preq->source.value.advance;
477 cost = imprcost;
478 }
479 } else if (!dai_can_requirement_be_met_in_city(preq, pplayer,
480 pcity)) {
482 }
483 }
485 }
486
490 best_cost = cost;
492 }
493 }
495
496 if (A_NEVER != best_tech) {
497 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
498
499 /* Crank up chosen tech want */
500 if (best_avl != NULL
502 /* We already have almost as good unit suitable for defending against this attacker */
503 want /= 2;
504 }
505
506 plr_data->tech_want[advance_index(best_tech)] += want;
507 TECH_LOG(ait, LOG_DEBUG, pplayer, best_tech,
508 "+ %d for %s by role",
509 want,
511 }
512
513 return best_avl;
514}
515
516/**********************************************************************/
522struct unit_type *dai_wants_role_unit(struct ai_type *ait, struct player *pplayer,
523 struct city *pcity, int role, int want)
524{
525 struct research *presearch = research_get(pplayer);
526 int i, n;
528 struct advance *best_tech = A_NEVER;
529 struct unit_type *best_unit = NULL;
530 struct unit_type *build_unit = NULL;
531 const struct civ_map *nmap = &(wld.map);
532
534 for (i = n - 1; i >= 0; i--) {
535 struct unit_type *iunit = get_role_unit(role, i);
536
539 break;
541 const struct impr_type *building;
542 struct advance *itech = A_NEVER;
543 int cost = 0;
544
548 /* See if we want to invent this. */
551
552 if (cost == 0 || ucost < cost) {
553 cost = ucost;
554 itech = padv;
555 }
556 }
558
560 if (building != NULL
561 && !can_player_build_improvement_direct(pplayer, building)) {
563 if (VUT_ADVANCE == preq->source.kind && preq->present) {
564 int iimprtech = advance_number(preq->source.value.advance);
565
567 iimprtech)) {
569 iimprtech);
570
571 if (imprcost < cost || cost == 0) {
572 /* If we already have the primary tech (cost == 0),
573 * or the building's tech is cheaper,
574 * go for the building's required tech. */
575 itech = preq->source.value.advance;
576 cost = imprcost;
577 }
578 }
579 }
581 }
582
583 if (cost < best_cost && itech != A_NEVER
586 best_cost = cost;
588 }
589 }
590 }
591
592 if (A_NEVER != best_tech) {
593 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
594
595 /* Crank up chosen tech want */
596 if (build_unit != NULL) {
597 /* We already have a role unit of this kind */
598 want /= 2;
599 }
600 plr_data->tech_want[advance_index(best_tech)] += want;
601 TECH_LOG(ait, LOG_DEBUG, pplayer, best_tech,
602 "+ %d for %s by role",
603 want,
605 }
606
607 return build_unit;
608}
609
610/**********************************************************************/
613void dai_clear_tech_wants(struct ai_type *ait, struct player *pplayer)
614{
615 struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
616
618 plr_data->tech_want[i] = 0;
620}
struct adv_data * adv_data_get(struct player *pplayer, bool *caller_closes)
Definition advdata.c:606
#define n
Definition astring.c:77
bool is_capital(const struct city *pcity)
Definition city.c:1579
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 can_city_build_unit_later(const struct civ_map *nmap, const struct city *pcity, const struct unit_type *punittype)
Definition city.c:970
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define city_list_iterate_end
Definition city.h:507
int combat_bonus_against(const struct combat_bonus_list *list, const struct unit_type *enemy, enum combat_bonus_type type)
Definition combat.c:1007
char * incite_cost
Definition comments.c:76
adv_want dai_city_want(struct player *pplayer, struct city *acity, struct adv_data *adv, struct impr_type *pimprove)
Definition daicity.c:1426
bool dai_can_requirement_be_met_in_city(const struct requirement *preq, const struct player *pplayer, const struct city *pcity)
Definition daieffects.c:821
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
static adv_want dai_tech_base_want(struct ai_type *ait, struct player *pplayer, struct city *pcity, struct advance *padv)
Definition daitech.c:225
struct unit_type * dai_wants_defender_against(struct ai_type *ait, const struct civ_map *nmap, struct player *pplayer, struct city *pcity, const struct unit_type *att, int want)
Definition daitech.c:390
void dai_clear_tech_wants(struct ai_type *ait, struct player *pplayer)
Definition daitech.c:613
void dai_manage_tech(struct ai_type *ait, struct player *pplayer)
Definition daitech.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 daitech.c:70
static void dai_tech_effect_values(struct ai_type *ait, struct player *pplayer)
Definition daitech.c:251
struct unit_type * dai_wants_role_unit(struct ai_type *ait, struct player *pplayer, struct city *pcity, int role, int want)
Definition daitech.c:522
const struct impr_type * utype_needs_improvement(const struct unit_type *putype, const struct city *pcity)
Definition daiunit.c:2902
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 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:1031
#define effect_list_iterate_end
Definition effects.h:81
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:79
float adv_want
Definition fc_types.h:1063
int Tech_type_id
Definition fc_types.h:236
@ RPT_CERTAIN
Definition fc_types.h:533
@ RPT_POSSIBLE
Definition fc_types.h:532
#define ADV_WANT_PRINTF
Definition fc_types.h:1064
struct civ_game game
Definition game.c:61
struct world wld
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:116
@ LOG_DEBUG
Definition log.h:35
const char * player_name(const struct player *pplayer)
Definition player.c:895
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define is_ai(plr)
Definition player.h:232
int normal_player_count(void)
Definition plrhand.c:3209
bool is_req_active(const struct req_context *context, const struct req_context *other_context, 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 daitech.c:49
adv_want want
Definition daitech.c:50
adv_want current_want
Definition daitech.c:51
Definition ai.h:50
Definition city.h:317
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:281
struct team * team
Definition player.h:261
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
struct tile * tile
Definition unit.h:142
enum universals_n kind
Definition fc_types.h:608
struct civ_map map
#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:309
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:248
#define A_NEVER
Definition tech.h:51
#define advance_index_iterate_end
Definition tech.h:244
#define advance_index_iterate_max_end
Definition tech.h:254
static Tech_type_id advance_count(void)
Definition tech.h:165
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:271
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:272
#define advance_index_iterate(_start, _index)
Definition tech.h:240
void choose_tech_goal(struct research *presearch, Tech_type_id tech)
Definition techtools.c:1075
void choose_tech(struct research *research, Tech_type_id tech)
Definition techtools.c:1005
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2259
int num_role_units(int role)
Definition unittype.c:2209
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1584
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
#define unit_tech_reqs_iterate_end
Definition unittype.h:888
#define unit_tech_reqs_iterate(_utype_, _p)
Definition unittype.h:882
#define unit_type_iterate(_p)
Definition unittype.h:862
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:869