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)
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 *****************************************************************************/
15 #include <fc_config.h>
29 /*****************************************************************************
30 Initialise citizens data.
31 *****************************************************************************/
32 void citizens_init(struct city
*pcity
)
36 if (game
.info
.citizen_nationality
!= TRUE
) {
40 /* For the nationality of the citizens the informations for all player
41 * slots are allocated as once. Considering a size of citizens (= char)
42 * this results in an allocation of 2 * 128 * 1 bytes for the citizens
43 * per nation as well as the timer for a nationality change. */
44 if (pcity
->nationality
== NULL
) {
45 /* Allocate the memory*/
46 pcity
->nationality
= fc_calloc(MAX_NUM_PLAYER_SLOTS
,
47 sizeof(*pcity
->nationality
));
49 /* Reset the nationality information. */
50 memset(pcity
->nationality
, 0,
51 MAX_NUM_PLAYER_SLOTS
* sizeof(*pcity
->nationality
));
55 /*****************************************************************************
57 *****************************************************************************/
58 void citizens_free(struct city
*pcity
)
62 if (pcity
->nationality
) {
63 free(pcity
->nationality
);
64 pcity
->nationality
= NULL
;
68 /*****************************************************************************
69 Get the number of citizens with the given nationality.
71 The player_slot has to be used as the client does not has the exact
72 knowledge about the players at certain points (especially at connecting).
73 *****************************************************************************/
74 citizens
citizens_nation_get(const struct city
*pcity
,
75 const struct player_slot
*pslot
)
77 if (game
.info
.citizen_nationality
!= TRUE
) {
81 fc_assert_ret_val(pslot
!= NULL
, 0);
82 fc_assert_ret_val(pcity
!= NULL
, 0);
83 fc_assert_ret_val(pcity
->nationality
!= NULL
, 0);
85 return *(pcity
->nationality
+ player_slot_index(pslot
));
88 /*****************************************************************************
89 Get the number of foreign citizens.
90 *****************************************************************************/
91 citizens
citizens_nation_foreign(const struct city
*pcity
)
93 return citizens_count(pcity
)
94 - citizens_nation_get(pcity
, city_owner(pcity
)->slot
);
97 /*****************************************************************************
98 Add a (positive or negative) value to the citizens of the given nationality.
99 As citizens is an unsigned value use int for the parameter 'add'.
101 The player_slot has to be used as the client does not has the exact
102 knowledge about the players at certain points (especially at connecting).
103 *****************************************************************************/
104 void citizens_nation_add(struct city
*pcity
, const struct player_slot
*pslot
,
107 citizens nationality
= citizens_nation_get(pcity
, pslot
);
109 if (game
.info
.citizen_nationality
!= TRUE
) {
113 fc_assert_ret(pslot
!= NULL
);
114 fc_assert_ret(pcity
!= NULL
);
115 fc_assert_ret(pcity
->nationality
!= NULL
);
117 fc_assert_ret(MAX_CITY_SIZE
- nationality
> add
);
118 fc_assert_ret(nationality
>= -add
);
120 citizens_nation_set(pcity
, pslot
, nationality
+ add
);
123 /*****************************************************************************
124 Convert a (positive or negative) value to the citizens from one nation to
125 another. As citizens is an unsigned value use int for the parameter 'move'.
127 The player_slot has to be used as the client does not has the exact
128 knowledge about the players at certain points (especially at connecting).
129 *****************************************************************************/
130 void citizens_nation_move(struct city
*pcity
,
131 const struct player_slot
*pslot_from
,
132 const struct player_slot
*pslot_to
,
135 citizens_nation_add(pcity
, pslot_from
, -move
);
136 citizens_nation_add(pcity
, pslot_to
, move
);
139 /*****************************************************************************
140 Set the number of citizens with the given nationality.
142 The player_slot has to be used as the client does not has the exact
143 knowledge about the players at certain points (especially at connecting).
144 *****************************************************************************/
145 void citizens_nation_set(struct city
*pcity
, const struct player_slot
*pslot
,
148 if (game
.info
.citizen_nationality
!= TRUE
) {
152 fc_assert_ret(pslot
!= NULL
);
153 fc_assert_ret(pcity
!= NULL
);
154 fc_assert_ret(pcity
->nationality
!= NULL
);
156 *(pcity
->nationality
+ player_slot_index(pslot
)) = count
;
159 /*****************************************************************************
160 Return the number of citizens in a city.
161 *****************************************************************************/
162 citizens
citizens_count(const struct city
*pcity
)
164 /* Use int here to check for an possible overflow at the end. */
167 if (game
.info
.citizen_nationality
!= TRUE
) {
168 return city_size_get(pcity
);
171 citizens_iterate(pcity
, pslot
, nationality
) {
172 /* If the citizens of a nation is greater than 0 there should be a player
173 * for this nation. This test should only be done on the server as the
174 * client does not has the knowledge about all players all the time. */
175 fc_assert_ret_val(!is_server() || player_slot_get_player(pslot
) != NULL
,
176 city_size_get(pcity
));
178 count
+= nationality
;
179 } citizens_iterate_end
;
181 fc_assert_ret_val(count
>= 0 && count
<= MAX_CITY_SIZE
,
182 city_size_get(pcity
));
184 return (citizens
)count
;
187 /*****************************************************************************
188 Return random citizen from city.
189 *****************************************************************************/
190 struct player_slot
*citizens_random(const struct city
*pcity
)
192 int total
= citizens_count(pcity
);
193 int chocen
= fc_rand(total
);
195 citizens_iterate(pcity
, pslot
, nationality
) {
196 chocen
-= nationality
;
200 } citizens_iterate_end
;