Freeciv21
Develop your civilization from humble roots to a global empire
difficulty.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <QBitArray>
15 // utility
16 #include "astring.h"
17 #include "fcintl.h"
18 #include "rand.h"
19 
20 // common
21 #include "player.h"
22 
23 // ai
24 #include "handicaps.h"
25 
26 #include "difficulty.h"
27 
28 static QBitArray *handicap_of_skill_level(enum ai_level level);
29 static int fuzzy_of_skill_level(enum ai_level level);
30 static int science_cost_of_skill_level(enum ai_level level);
31 static int expansionism_of_skill_level(enum ai_level level);
32 
36 void set_ai_level_directer(struct player *pplayer, enum ai_level level)
37 {
42  pplayer->ai_common.skill_level = level;
43 }
44 
48 static QBitArray *handicap_of_skill_level(enum ai_level level)
49 {
50  QBitArray *handicap = new QBitArray(H_LAST);
51 
52  fc_assert(ai_level_is_valid(level));
53 
54  switch (level) {
55  case AI_LEVEL_AWAY:
56  handicap->setBit(H_AWAY);
57  handicap->setBit(H_FOG);
58  handicap->setBit(H_MAP);
59  handicap->setBit(H_RATES);
60  handicap->setBit(H_TARGETS);
61  handicap->setBit(H_HUTS);
62  handicap->setBit(H_REVOLUTION);
63  handicap->setBit(H_PRODCHGPEN);
64  break;
65  case AI_LEVEL_NOVICE:
66  case AI_LEVEL_HANDICAPPED:
67  handicap->setBit(H_RATES);
68  handicap->setBit(H_TARGETS);
69  handicap->setBit(H_HUTS);
70  handicap->setBit(H_NOPLANES);
71  handicap->setBit(H_DIPLOMAT);
72  handicap->setBit(H_LIMITEDHUTS);
73  handicap->setBit(H_DEFENSIVE);
74  handicap->setBit(H_DIPLOMACY);
75  handicap->setBit(H_REVOLUTION);
76  handicap->setBit(H_EXPANSION);
77  handicap->setBit(H_DANGER);
78  handicap->setBit(H_CEASEFIRE);
79  handicap->setBit(H_NOBRIBE_WF);
80  handicap->setBit(H_PRODCHGPEN);
81  break;
82  case AI_LEVEL_EASY:
83  handicap->setBit(H_RATES);
84  handicap->setBit(H_TARGETS);
85  handicap->setBit(H_HUTS);
86  handicap->setBit(H_NOPLANES);
87  handicap->setBit(H_DIPLOMAT);
88  handicap->setBit(H_LIMITEDHUTS);
89  handicap->setBit(H_DEFENSIVE);
90  handicap->setBit(H_DIPLOMACY);
91  handicap->setBit(H_REVOLUTION);
92  handicap->setBit(H_EXPANSION);
93  handicap->setBit(H_CEASEFIRE);
94  handicap->setBit(H_NOBRIBE_WF);
95  break;
96  case AI_LEVEL_NORMAL:
97  handicap->setBit(H_RATES);
98  handicap->setBit(H_TARGETS);
99  handicap->setBit(H_HUTS);
100  handicap->setBit(H_DIPLOMAT);
101  handicap->setBit(H_CEASEFIRE);
102  handicap->setBit(H_NOBRIBE_WF);
103  break;
104 
105 #ifdef FREECIV_DEBUG
106  case AI_LEVEL_EXPERIMENTAL:
107  handicap->setBit(H_EXPERIMENTAL);
108  break;
109 #endif // FREECIV_DEBUG
110 
111  case AI_LEVEL_CHEATING:
112  handicap->setBit(H_RATES);
113  break;
114  case AI_LEVEL_HARD:
115  // No handicaps
116  break;
117  case AI_LEVEL_COUNT:
118  fc_assert(level != AI_LEVEL_COUNT);
119  break;
120  }
121 
122  return handicap;
123 }
124 
129 static int fuzzy_of_skill_level(enum ai_level level)
130 {
131  fc_assert(ai_level_is_valid(level));
132 
133  switch (level) {
134  case AI_LEVEL_AWAY:
135  return 0;
136  case AI_LEVEL_HANDICAPPED:
137  case AI_LEVEL_NOVICE:
138  return 400;
139  case AI_LEVEL_EASY:
140  return 300;
141  case AI_LEVEL_NORMAL:
142  case AI_LEVEL_HARD:
143  case AI_LEVEL_CHEATING:
144 #ifdef FREECIV_DEBUG
145  case AI_LEVEL_EXPERIMENTAL:
146 #endif // FREECIV_DEBUG
147  return 0;
148  case AI_LEVEL_COUNT:
149  fc_assert(level != AI_LEVEL_COUNT);
150  return 0;
151  }
152 
153  return 0;
154 }
155 
163 static int science_cost_of_skill_level(enum ai_level level)
164 {
165  fc_assert(ai_level_is_valid(level));
166 
167  switch (level) {
168  case AI_LEVEL_AWAY:
169  return 100;
170  case AI_LEVEL_HANDICAPPED:
171  case AI_LEVEL_NOVICE:
172  return 250;
173  case AI_LEVEL_EASY:
174  case AI_LEVEL_NORMAL:
175  case AI_LEVEL_HARD:
176  case AI_LEVEL_CHEATING:
177 #ifdef FREECIV_DEBUG
178  case AI_LEVEL_EXPERIMENTAL:
179 #endif // FREECIV_DEBUG
180  return 100;
181  case AI_LEVEL_COUNT:
182  fc_assert(level != AI_LEVEL_COUNT);
183  return 100;
184  }
185 
186  return 100;
187 }
188 
194 static int expansionism_of_skill_level(enum ai_level level)
195 {
196  fc_assert(ai_level_is_valid(level));
197 
198  switch (level) {
199  case AI_LEVEL_AWAY:
200  return 0;
201  case AI_LEVEL_HANDICAPPED:
202  case AI_LEVEL_NOVICE:
203  case AI_LEVEL_EASY:
204  return 10;
205  case AI_LEVEL_NORMAL:
206  case AI_LEVEL_HARD:
207  case AI_LEVEL_CHEATING:
208 #ifdef FREECIV_DEBUG
209  case AI_LEVEL_EXPERIMENTAL:
210 #endif // FREECIV_DEBUG
211  return 100;
212  case AI_LEVEL_COUNT:
213  fc_assert(level != AI_LEVEL_COUNT);
214  return 100;
215  }
216 
217  return 100;
218 }
219 
225 char *ai_level_help(const char *cmdname)
226 {
227  // Translate cmdname to AI level.
228  enum ai_level level = ai_level_by_name(cmdname, fc_strcasecmp);
229  QString help, features;
230  QBitArray *handicaps;
231  int h;
232 
233  fc_assert(ai_level_is_valid(level));
234 
235  if (level == AI_LEVEL_AWAY) {
236  // Special case
237  help = _("Toggles 'away' mode for your nation. In away mode, "
238  "the AI will govern your nation but make only minimal "
239  "changes.");
240  } else {
241  // TRANS: %s is a (translated) skill level ('Novice', 'Hard', etc)
242  help = QString(_("With no arguments, sets all AI players to skill level "
243  "'%1', and sets the default level for any new AI "
244  "players to '%2'. With an argument, sets the skill "
245  "level for the specified player only."))
246  .arg(_(ai_level_name(level)), _(ai_level_name(level)));
247  }
248 
249  handicaps = handicap_of_skill_level(level);
250  for (h = 0; h < H_LAST; h++) {
251  bool inverted;
252  const char *desc =
253  handicap_desc(static_cast<handicap_type>(h), &inverted);
254 
255  if (desc && handicaps->at(h) != inverted) {
256  features += desc + qendl();
257  }
258  }
259 
260  if (fuzzy_of_skill_level(level) > 0) {
261  features += _("Has erratic decision-making.") + qendl();
262  }
263  {
264  int science = science_cost_of_skill_level(level);
265 
266  if (science != 100) {
267  features +=
268  QString(_("Research takes %1 as long as usual.")).arg(science);
269  }
270  }
271  if (expansionism_of_skill_level(level) < 100) {
272  features += _("Has reduced appetite for expansion.");
273  } // no level currently has >100, so no string yet
274 
275  switch (level) {
276  case AI_LEVEL_HANDICAPPED:
277  // TRANS: describing an AI skill level
278  help += _("\nThis skill level has the same features as 'Novice', "
279  "but may suffer additional ruleset-defined penalties.")
280  + qendl();
281  break;
282  case AI_LEVEL_CHEATING:
283  // TRANS: describing an AI skill level
284  help += _("\nThis skill level has the same features as 'Hard', "
285  "but may enjoy additional ruleset-defined bonuses.")
286  + qendl();
287  break;
288  default:
289  // TRANS: describing an AI skill level
290  help += _("\nThis skill level's features include the following. "
291  "(Some rulesets may define extra level-specific "
292  "behavior.)")
293  + qendl();
294  break;
295  }
296 
297  help += features;
298  delete handicaps;
299  return qstrdup(const_cast<char *>(qUtf8Printable(help)));
300 }
301 
318 bool ai_fuzzy(const struct player *pplayer, bool normal_decision)
319 {
320  if (!is_ai(pplayer) || pplayer->ai_common.fuzzy == 0) {
321  return normal_decision;
322  }
323  if (fc_rand(1000) >= pplayer->ai_common.fuzzy) {
324  return normal_decision;
325  }
326  return !normal_decision;
327 }
QString qendl()
Definition: astring.cpp:65
static QBitArray * handicap_of_skill_level(enum ai_level level)
Returns handicap bitvector for given AI skill level.
Definition: difficulty.cpp:48
static int fuzzy_of_skill_level(enum ai_level level)
Return the AI fuzziness (0 to 1000) corresponding to a given skill level (1 to 10).
Definition: difficulty.cpp:129
char * ai_level_help(const char *cmdname)
Helper function for skill level command help.
Definition: difficulty.cpp:225
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Set an AI level and related quantities, with no feedback.
Definition: difficulty.cpp:36
static int expansionism_of_skill_level(enum ai_level level)
Return the AI expansion tendency, a percentage factor to value new cities, compared to defaults.
Definition: difficulty.cpp:194
static int science_cost_of_skill_level(enum ai_level level)
Return the AI's science development cost; a science development cost of 100 means that the AI develop...
Definition: difficulty.cpp:163
bool ai_fuzzy(const struct player *pplayer, bool normal_decision)
Return the value normal_decision (a boolean), except if the AI is fuzzy, then sometimes flip the valu...
Definition: difficulty.cpp:318
#define _(String)
Definition: fcintl.h:50
void handicaps_set(struct player *pplayer, QBitArray *handicaps)
Set player handicaps.
Definition: handicaps.cpp:50
const char * handicap_desc(enum handicap_type htype, bool *inverted)
Return a short (translated) string describing the handicap, for help.
Definition: handicaps.cpp:76
handicap_type
Definition: handicaps.h:16
@ H_LAST
Definition: handicaps.h:35
@ H_MAP
Definition: handicaps.h:27
@ H_REVOLUTION
Definition: handicaps.h:29
@ H_DIPLOMACY
Definition: handicaps.h:28
@ H_DIPLOMAT
Definition: handicaps.h:17
@ H_TARGETS
Definition: handicaps.h:23
@ H_LIMITEDHUTS
Definition: handicaps.h:19
@ H_RATES
Definition: handicaps.h:22
@ H_AWAY
Definition: handicaps.h:18
@ H_HUTS
Definition: handicaps.h:24
@ H_EXPERIMENTAL
Definition: handicaps.h:21
@ H_DEFENSIVE
Definition: handicaps.h:20
@ H_DANGER
Definition: handicaps.h:31
@ H_NOBRIBE_WF
Definition: handicaps.h:33
@ H_NOPLANES
Definition: handicaps.h:26
@ H_FOG
Definition: handicaps.h:25
@ H_PRODCHGPEN
Definition: handicaps.h:34
@ H_EXPANSION
Definition: handicaps.h:30
@ H_CEASEFIRE
Definition: handicaps.h:32
#define fc_assert(condition)
Definition: log.h:89
#define is_ai(plr)
Definition: player.h:227
#define fc_rand(_size)
Definition: rand.h:16
struct setting_list * level[OLEVELS_NUM]
Definition: settings.cpp:167
enum ai_level skill_level
Definition: player.h:109
int science_cost
Definition: player.h:112
int expand
Definition: player.h:111
int fuzzy
Definition: player.h:110
Definition: player.h:231
struct player_ai ai_common
Definition: player.h:270
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89