Stop sharing requirement_unit_state_ereq().
[freeciv.git] / common / citizens.c
blob88f8195020ac0986fff275d2c0de3d22b97d0adc
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 "log.h"
20 #include "rand.h"
22 /* common */
23 #include "city.h"
24 #include "game.h"
25 #include "player.h"
27 #include "citizens.h"
29 /*****************************************************************************
30 Initialise citizens data.
31 *****************************************************************************/
32 void citizens_init(struct city *pcity)
34 fc_assert_ret(pcity);
36 if (game.info.citizen_nationality != TRUE) {
37 return;
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));
48 } else {
49 /* Reset the nationality information. */
50 memset(pcity->nationality, 0,
51 MAX_NUM_PLAYER_SLOTS * sizeof(*pcity->nationality));
55 /*****************************************************************************
56 Free citizens data.
57 *****************************************************************************/
58 void citizens_free(struct city *pcity)
60 fc_assert_ret(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) {
78 return 0;
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,
105 int add)
107 citizens nationality = citizens_nation_get(pcity, pslot);
109 if (game.info.citizen_nationality != TRUE) {
110 return;
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,
133 int move)
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,
146 citizens count)
148 if (game.info.citizen_nationality != TRUE) {
149 return;
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. */
165 int count = 0;
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;
197 if (chocen <= 0) {
198 return pslot;
200 } citizens_iterate_end;
202 fc_assert(FALSE);
204 return NULL;