Freeciv-3.1: /fast/freeciv/nightly/S3_1/common/achievements.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
achievements.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 "fcintl.h"
20#include "log.h"
21#include "rand.h"
22#include "shared.h"
23
24/* common */
25#include "citizens.h"
26#include "city.h"
27#include "culture.h"
28#include "game.h"
29#include "map.h"
30#include "player.h"
31#include "spaceship.h"
32
33#include "achievements.h"
34
35 static struct achievement achievements[MAX_ACHIEVEMENT_TYPES];
36
37/************************************************************************/
40 void achievements_init(void)
41{
42 int i;
43
44 for (i = 0; i < ARRAY_SIZE(achievements); i++) {
45 achievements[i].id = i;
46 achievements[i].ruledit_disabled = FALSE;
47 achievements[i].first = NULL;
48 achievements[i].value = 0;
49 achievements[i].culture = 0;
50 BV_CLR_ALL(achievements[i].achievers);
51 achievements[i].first_msg = NULL;
52 achievements[i].cons_msg = NULL;
53 }
54}
55
56/************************************************************************/
59 void achievements_free(void)
60{
61 int i;
62
63 for (i = 0; i < ARRAY_SIZE(achievements); i++) {
64 if (achievements[i].first_msg != NULL) {
65 FC_FREE(achievements[i].first_msg);
66 }
67 if (achievements[i].cons_msg != NULL) {
68 FC_FREE(achievements[i].cons_msg);
69 }
70 }
71}
72
73/**********************************************************************/
76 int achievement_number(const struct achievement *pach)
77{
78 fc_assert_ret_val(NULL != pach, -1);
79
80 return pach->id;
81}
82
83/**********************************************************************/
86 int achievement_index(const struct achievement *pach)
87{
88 fc_assert_ret_val(NULL != pach, -1);
89
90 return pach - achievements;
91}
92
93/**********************************************************************/
96 struct achievement *achievement_by_number(int id)
97{
98 fc_assert_ret_val(id >= 0 && id < game.control.num_achievement_types, NULL);
99
100 return &achievements[id];
101}
102
103/**********************************************************************/
106 const char *achievement_name_translation(struct achievement *pach)
107{
108 return name_translation_get(&pach->name);
109}
110
111/**********************************************************************/
114 const char *achievement_rule_name(struct achievement *pach)
115{
116 return rule_name_get(&pach->name);
117}
118
119/**********************************************************************/
123 struct achievement *achievement_by_rule_name(const char *name)
124{
125 const char *qs = Qn_(name);
126
127 achievements_iterate(pach) {
128 if (!fc_strcasecmp(achievement_rule_name(pach), qs)) {
129 return pach;
130 }
131 } achievements_iterate_end;
132
133 return NULL;
134}
135
136/**********************************************************************/
140 struct player *achievement_plr(struct achievement *ach,
141 struct player_list *achievers)
142{
143 struct player *credited = NULL;
144
145 players_iterate(pplayer) {
146 if (achievement_check(ach, pplayer)) {
147 if (!ach->unique) {
148 pplayer->history += ach->culture;
149 BV_SET(ach->achievers, player_index(pplayer));
150 }
151 player_list_append(achievers, pplayer);
152 }
153 } players_iterate_end;
154
155 if (ach->first != NULL) {
156 /* Already have first one credited. */
157 return NULL;
158 }
159
160 if (player_list_size(achievers) > 0) {
161 /* If multiple players achieved at the same turn, randomly select one
162 * as the one who won the race. */
163 credited = player_list_get(achievers, fc_rand(player_list_size(achievers)));
164
165 ach->first = credited;
166
167 if (ach->unique) {
168 /* For !ach->unique achievements culture was already added above. */
169 credited->history += ach->culture;
170 }
171
172 /* Mark the selected player as the only one having the achievement */
173 BV_SET(ach->achievers, player_index(credited));
174 }
175
176 return credited;
177}
178
179/**********************************************************************/
182 bool achievement_check(struct achievement *ach, struct player *pplayer)
183{
184 if ((ach->unique && ach->first != NULL)
185 || (BV_ISSET(ach->achievers, player_index(pplayer)))) {
186 /* It was already achieved */
187 return FALSE;
188 }
189
190 switch (ach->type) {
191 case ACHIEVEMENT_SPACESHIP:
192 return pplayer->spaceship.state == SSHIP_LAUNCHED;
193 case ACHIEVEMENT_MAP:
194 {
195 int max_unknown;
196 int required;
197 int total;
198 int known = 0;
199 int unknown = 0;
200
201 /* We calculate max_unknown first for getting the
202 * rounding correctly.
203 * Consider 50 tile map from which we want 25% known.
204 * 50 * 25% = 12.5. Would we round that number of tiles
205 * down, we would get < 25% that's minimum requirement.
206 * Instead we round down (50 - 12.5 = 37.5) -> 37 and then
207 * get the minimum number of full tiles as 50 - 37 = 13. */
208 total = map_num_tiles();
209 max_unknown = (total * (100 - ach->value)) / 100;
210 required = total - max_unknown;
211
212 whole_map_iterate(&(wld.map), ptile) {
213 bool this_is_known = FALSE;
214
215 if (is_server()) {
216 if (dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
217 this_is_known = TRUE;
218 }
219 } else {
220 /* Client */
221 if (ptile->terrain != T_UNKNOWN) {
222 this_is_known = TRUE;
223 }
224 }
225
226 if (this_is_known) {
227 known++;
228 if (known >= required) {
229 return TRUE;
230 }
231 } else {
232 unknown++;
233 if (unknown >= max_unknown) {
234 return FALSE;
235 }
236 }
237 } whole_map_iterate_end;
238 }
239
240 return FALSE;
241 case ACHIEVEMENT_MULTICULTURAL:
242 {
243 bv_player seen_citizens;
244 int count = 0;
245
246 BV_CLR_ALL(seen_citizens);
247
248 city_list_iterate(pplayer->cities, pcity) {
249 citizens_iterate(pcity, pslot, pnat) {
250 int idx = player_index(player_slot_get_player(pslot));
251
252 if (!BV_ISSET(seen_citizens, idx)) {
253 BV_SET(seen_citizens, idx);
254 count++;
255 if (count >= ach->value) {
256 /* There's at least value different nationalities. */
257 return TRUE;
258 }
259 }
260 } citizens_iterate_end;
261 } city_list_iterate_end;
262 }
263
264 return FALSE;
265 case ACHIEVEMENT_CULTURED_CITY:
266 city_list_iterate(pplayer->cities, pcity) {
267 if (city_culture(pcity) >= ach->value) {
268 return TRUE;
269 }
270 } city_list_iterate_end;
271
272 return FALSE;
273 case ACHIEVEMENT_CULTURED_NATION:
274 if (player_culture(pplayer) >= ach->value) {
275 return TRUE;
276 }
277
278 return FALSE;
279 case ACHIEVEMENT_LUCKY:
280 return ((int)fc_rand(10000) < ach->value);
281 case ACHIEVEMENT_HUTS:
282 return pplayer->server.huts >= ach->value;
283 case ACHIEVEMENT_METROPOLIS:
284 city_list_iterate(pplayer->cities, pcity) {
285 if (city_size_get(pcity) >= ach->value) {
286 return TRUE;
287 }
288 } city_list_iterate_end;
289
290 return FALSE;
291 case ACHIEVEMENT_LITERATE:
292 return get_literacy(pplayer) >= ach->value;
293 case ACHIEVEMENT_LAND_AHOY:
294 {
295 bool *seen = fc_calloc(wld.map.num_continents, sizeof(bool));
296 int count = 0;
297
298 whole_map_iterate(&(wld.map), ptile) {
299 bool this_is_known = FALSE;
300
301 if (is_server()) {
302 if (dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
303 this_is_known = TRUE;
304 }
305 } else {
306 /* Client */
307 if (ptile->terrain != T_UNKNOWN) {
308 this_is_known = TRUE;
309 }
310 }
311
312 if (this_is_known) {
313 /* FIXME: This makes the assumption that fogged tiles belonged
314 * to their current continent when they were last seen. */
315 if (ptile->continent > 0 && !seen[ptile->continent - 1]) {
316 if (++count >= ach->value) {
317 free(seen);
318 return TRUE;
319 }
320 seen[ptile->continent - 1] = TRUE;
321 }
322 }
323 } whole_map_iterate_end;
324
325 free(seen);
326 return FALSE;
327 }
328 case ACHIEVEMENT_COUNT:
329 break;
330 }
331
332 log_error("achievement_check(): Illegal achievement type %d", ach->type);
333
334 return FALSE;
335}
336
337/**********************************************************************/
340 const char *achievement_first_msg(struct achievement *pach)
341{
342 fc_assert(pach->first_msg != NULL);
343
344 return _(pach->first_msg);
345}
346
347/**********************************************************************/
350 const char *achievement_later_msg(struct achievement *pach)
351{
352 fc_assert(pach->cons_msg != NULL);
353
354 return _(pach->cons_msg);
355}
356
357/**********************************************************************/
360 bool achievement_player_has(const struct achievement *pach,
361 const struct player *pplayer)
362{
363 if (pplayer == NULL) {
364 return FALSE;
365 }
366
367 return BV_ISSET(pach->achievers, player_index(pplayer));
368}
369
370/**********************************************************************/
373 bool achievement_claimed(const struct achievement *pach)
374{
375 return pach->first != NULL;
376}
377
378/**********************************************************************/
382 int get_literacy(const struct player *pplayer)
383{
384 int pop = pplayer->score.population;
385
386 if (pop <= 0) {
387 return 0;
388 } else if (pop >= 10000) {
389 return pplayer->score.literacy / (pop / 100);
390 } else {
391 return (pplayer->score.literacy * 100) / pop;
392 }
393}
achievement_check
bool achievement_check(struct achievement *ach, struct player *pplayer)
Definition achievements.c:182
achievements_free
void achievements_free(void)
Definition achievements.c:59
achievement_player_has
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
Definition achievements.c:360
achievements
static struct achievement achievements[MAX_ACHIEVEMENT_TYPES]
Definition achievements.c:35
achievement_index
int achievement_index(const struct achievement *pach)
Definition achievements.c:86
achievement_plr
struct player * achievement_plr(struct achievement *ach, struct player_list *achievers)
Definition achievements.c:140
achievement_by_number
struct achievement * achievement_by_number(int id)
Definition achievements.c:96
get_literacy
int get_literacy(const struct player *pplayer)
Definition achievements.c:382
achievement_later_msg
const char * achievement_later_msg(struct achievement *pach)
Definition achievements.c:350
achievement_number
int achievement_number(const struct achievement *pach)
Definition achievements.c:76
achievement_first_msg
const char * achievement_first_msg(struct achievement *pach)
Definition achievements.c:340
achievement_rule_name
const char * achievement_rule_name(struct achievement *pach)
Definition achievements.c:114
achievement_by_rule_name
struct achievement * achievement_by_rule_name(const char *name)
Definition achievements.c:123
achievement_name_translation
const char * achievement_name_translation(struct achievement *pach)
Definition achievements.c:106
achievements_init
void achievements_init(void)
Definition achievements.c:40
achievement_claimed
bool achievement_claimed(const struct achievement *pach)
Definition achievements.c:373
achievements.h
achievements_iterate_end
#define achievements_iterate_end
Definition achievements.h:70
achievements_iterate
#define achievements_iterate(_ach_)
Definition achievements.h:64
dbv_isset
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
citizens.h
citizens_iterate_end
#define citizens_iterate_end
Definition citizens.h:54
citizens_iterate
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
city.h
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:488
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:490
city_culture
int city_culture(const struct city *pcity)
Definition culture.c:29
player_culture
int player_culture(const struct player *plr)
Definition culture.c:46
culture.h
id
int int id
Definition editgui_g.h:28
is_server
static bool is_server(void)
Definition fc_interface.h:69
MAX_ACHIEVEMENT_TYPES
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
fcintl.h
_
#define _(String)
Definition fcintl.h:67
Qn_
#define Qn_(String)
Definition fcintl.h:89
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game.h
name
const char * name
Definition inputfile.c:127
log.h
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_error
#define log_error(message,...)
Definition log.h:103
map_num_tiles
int map_num_tiles(void)
Definition map.c:1012
map.h
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:539
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:548
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
rule_name_get
static const char * rule_name_get(const struct name_translation *ptrans)
Definition name_translation.h:112
name_translation_get
static const char * name_translation_get(const struct name_translation *ptrans)
Definition name_translation.h:121
player_index
int player_index(const struct player *pplayer)
Definition player.c:820
player_slot_get_player
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:430
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
shared.h
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
spaceship.h
SSHIP_LAUNCHED
@ SSHIP_LAUNCHED
Definition spaceship.h:85
achievement
Definition achievements.h:26
achievement::first_msg
char * first_msg
Definition achievements.h:38
achievement::type
enum achievement_type type
Definition achievements.h:30
achievement::first
struct player * first
Definition achievements.h:34
achievement::value
int value
Definition achievements.h:31
achievement::achievers
bv_player achievers
Definition achievements.h:35
achievement::cons_msg
char * cons_msg
Definition achievements.h:39
achievement::unique
bool unique
Definition achievements.h:32
achievement::culture
int culture
Definition achievements.h:33
achievement::name
struct name_translation name
Definition achievements.h:28
achievement::ruledit_disabled
bool ruledit_disabled
Definition achievements.h:29
achievement::id
int id
Definition achievements.h:27
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
civ_map::num_continents
int num_continents
Definition map_types.h:78
packet_ruleset_control::num_achievement_types
int num_achievement_types
Definition packets_gen.h:1466
player_score::population
int population
Definition player.h:103
player_score::literacy
int literacy
Definition player.h:107
player_spaceship::state
enum spaceship_state state
Definition spaceship.h:108
player
Definition player.h:249
player::cities
struct city_list * cities
Definition player.h:281
player::tile_known
struct dbv tile_known
Definition player.h:306
player::huts
int huts
Definition player.h:349
player::spaceship
struct player_spaceship spaceship
Definition player.h:286
player::score
struct player_score score
Definition player.h:283
player::server
struct player::@69::@71 server
player::history
int history
Definition player.h:312
world::map
struct civ_map map
Definition world_object.h:38
fc_strcasecmp
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
T_UNKNOWN
#define T_UNKNOWN
Definition terrain.h:57
tile_index
#define tile_index(_pt_)
Definition tile.h:87