Do not return NULL as boolean from wonder_is_lost() nor wonder_is_built()
[freeciv.git] / ai / difficulty.c
blobd00ca009c5f9082cd4bdfc758784df3782ff77d0
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "bitvector.h"
20 #include "rand.h"
22 /* common */
23 #include "player.h"
25 /* ai */
26 #include "handicaps.h"
28 #include "difficulty.h"
30 static bv_handicap handicap_of_skill_level(enum ai_level level);
31 static int fuzzy_of_skill_level(enum ai_level level);
32 static int science_cost_of_skill_level(enum ai_level level);
33 static int expansionism_of_skill_level(enum ai_level level);
35 /**************************************************************************
36 Set an AI level and related quantities, with no feedback.
37 **************************************************************************/
38 void set_ai_level_directer(struct player *pplayer, enum ai_level level)
40 handicaps_set(pplayer, handicap_of_skill_level(level));
41 pplayer->ai_common.fuzzy = fuzzy_of_skill_level(level);
42 pplayer->ai_common.expand = expansionism_of_skill_level(level);
43 pplayer->ai_common.science_cost = science_cost_of_skill_level(level);
44 pplayer->ai_common.skill_level = level;
47 /**************************************************************************
48 Returns handicap bitvector for given AI skill level
49 **************************************************************************/
50 static bv_handicap handicap_of_skill_level(enum ai_level level)
52 bv_handicap handicap;
54 fc_assert(ai_level_is_valid(level));
56 BV_CLR_ALL(handicap);
58 switch (level) {
59 case AI_LEVEL_AWAY:
60 BV_SET(handicap, H_AWAY);
61 BV_SET(handicap, H_FOG);
62 BV_SET(handicap, H_MAP);
63 BV_SET(handicap, H_RATES);
64 BV_SET(handicap, H_TARGETS);
65 BV_SET(handicap, H_HUTS);
66 BV_SET(handicap, H_REVOLUTION);
67 break;
68 case AI_LEVEL_NOVICE:
69 case AI_LEVEL_HANDICAPPED:
70 BV_SET(handicap, H_RATES);
71 BV_SET(handicap, H_TARGETS);
72 BV_SET(handicap, H_HUTS);
73 BV_SET(handicap, H_NOPLANES);
74 BV_SET(handicap, H_DIPLOMAT);
75 BV_SET(handicap, H_LIMITEDHUTS);
76 BV_SET(handicap, H_DEFENSIVE);
77 BV_SET(handicap, H_DIPLOMACY);
78 BV_SET(handicap, H_REVOLUTION);
79 BV_SET(handicap, H_EXPANSION);
80 BV_SET(handicap, H_DANGER);
81 BV_SET(handicap, H_CEASEFIRE);
82 break;
83 case AI_LEVEL_EASY:
84 BV_SET(handicap, H_RATES);
85 BV_SET(handicap, H_TARGETS);
86 BV_SET(handicap, H_HUTS);
87 BV_SET(handicap, H_NOPLANES);
88 BV_SET(handicap, H_DIPLOMAT);
89 BV_SET(handicap, H_LIMITEDHUTS);
90 BV_SET(handicap, H_DEFENSIVE);
91 BV_SET(handicap, H_DIPLOMACY);
92 BV_SET(handicap, H_REVOLUTION);
93 BV_SET(handicap, H_EXPANSION);
94 BV_SET(handicap, H_CEASEFIRE);
95 break;
96 case AI_LEVEL_NORMAL:
97 BV_SET(handicap, H_RATES);
98 BV_SET(handicap, H_TARGETS);
99 BV_SET(handicap, H_HUTS);
100 BV_SET(handicap, H_DIPLOMAT);
101 BV_SET(handicap, H_CEASEFIRE);
102 break;
104 #ifdef DEBUG
105 case AI_LEVEL_EXPERIMENTAL:
106 BV_SET(handicap, H_EXPERIMENTAL);
107 break;
108 #endif /* DEBUG */
110 case AI_LEVEL_CHEATING:
111 BV_SET(handicap, H_RATES);
112 break;
113 case AI_LEVEL_HARD:
114 /* No handicaps */
115 break;
116 case AI_LEVEL_COUNT:
117 fc_assert(level != AI_LEVEL_COUNT);
118 break;
121 return handicap;
124 /**************************************************************************
125 Return the AI fuzziness (0 to 1000) corresponding to a given skill
126 level (1 to 10). See ai_fuzzy() in common/player.c
127 **************************************************************************/
128 static int fuzzy_of_skill_level(enum ai_level level)
130 fc_assert(ai_level_is_valid(level));
132 switch(level) {
133 case AI_LEVEL_AWAY:
134 return 0;
135 case AI_LEVEL_HANDICAPPED:
136 case AI_LEVEL_NOVICE:
137 return 400;
138 case AI_LEVEL_EASY:
139 return 300;
140 case AI_LEVEL_NORMAL:
141 case AI_LEVEL_HARD:
142 case AI_LEVEL_CHEATING:
143 #ifdef DEBUG
144 case AI_LEVEL_EXPERIMENTAL:
145 #endif /* DEBUG */
146 return 0;
147 case AI_LEVEL_COUNT:
148 fc_assert(level != AI_LEVEL_COUNT);
149 return 0;
152 return 0;
155 /**************************************************************************
156 Return the AI's science development cost; a science development cost of 100
157 means that the AI develops science at the same speed as a human; a science
158 development cost of 200 means that the AI develops science at half the speed
159 of a human, and a sceence development cost of 50 means that the AI develops
160 science twice as fast as the human.
161 **************************************************************************/
162 static int science_cost_of_skill_level(enum ai_level level)
164 fc_assert(ai_level_is_valid(level));
166 switch(level) {
167 case AI_LEVEL_AWAY:
168 return 100;
169 case AI_LEVEL_HANDICAPPED:
170 case AI_LEVEL_NOVICE:
171 return 250;
172 case AI_LEVEL_EASY:
173 case AI_LEVEL_NORMAL:
174 case AI_LEVEL_HARD:
175 case AI_LEVEL_CHEATING:
176 #ifdef DEBUG
177 case AI_LEVEL_EXPERIMENTAL:
178 #endif /* DEBUG */
179 return 100;
180 case AI_LEVEL_COUNT:
181 fc_assert(level != AI_LEVEL_COUNT);
182 return 100;
185 return 100;
188 /**************************************************************************
189 Return the AI expansion tendency, a percentage factor to value new cities,
190 compared to defaults. 0 means _never_ build new cities, > 100 means to
191 (over?)value them even more than the default (already expansionistic) AI.
192 **************************************************************************/
193 static int expansionism_of_skill_level(enum ai_level level)
195 fc_assert(ai_level_is_valid(level));
197 switch(level) {
198 case AI_LEVEL_AWAY:
199 return 0;
200 case AI_LEVEL_HANDICAPPED:
201 case AI_LEVEL_NOVICE:
202 case AI_LEVEL_EASY:
203 return 10;
204 case AI_LEVEL_NORMAL:
205 case AI_LEVEL_HARD:
206 case AI_LEVEL_CHEATING:
207 #ifdef DEBUG
208 case AI_LEVEL_EXPERIMENTAL:
209 #endif /* DEBUG */
210 return 100;
211 case AI_LEVEL_COUNT:
212 fc_assert(level != AI_LEVEL_COUNT);
213 return 100;
216 return 100;
219 /**************************************************************************
220 Return the value normal_decision (a boolean), except if the AI is fuzzy,
221 then sometimes flip the value. The intention of this is that instead of
222 if (condition) { action }
223 you can use
224 if (ai_fuzzy(pplayer, condition)) { action }
225 to sometimes flip a decision, to simulate an AI with some confusion,
226 indecisiveness, forgetfulness etc. In practice its often safer to use
227 if (condition && ai_fuzzy(pplayer,1)) { action }
228 for an action which only makes sense if condition holds, but which a
229 fuzzy AI can safely "forget". Note that for a non-fuzzy AI, or for a
230 human player being helped by the AI (eg, autosettlers), you can ignore
231 the "ai_fuzzy(pplayer," part, and read the previous example as:
232 if (condition && 1) { action }
233 --dwp
234 **************************************************************************/
235 bool ai_fuzzy(const struct player *pplayer, bool normal_decision)
237 if (!pplayer->ai_controlled || pplayer->ai_common.fuzzy == 0) {
238 return normal_decision;
240 if (fc_rand(1000) >= pplayer->ai_common.fuzzy) {
241 return normal_decision;
243 return !normal_decision;