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>
31 #include "sanitycheck.h"
34 #include "citizenshand.h"
36 #define log_citizens log_debug
39 /*****************************************************************************
40 Update the nationality according to the city size. New citiens are added
41 using the nationality of the owner. If the city size is reduced, the
42 citizens are removed first from the foreign citizens.
43 *****************************************************************************/
44 #define log_citizens_add(_pcity, _delta, _pplayer) \
45 log_citizens("%s (size %d; %s): %+d citizen(s) for %s (now: %d)", \
46 city_name(_pcity), city_size_get(_pcity), \
47 player_name(city_owner(_pcity)), _delta, \
48 player_name(_pplayer), \
49 citizens_nation_get(_pcity, _pplayer->slot));
50 void citizens_update(struct city
*pcity
, struct player
*plr
)
56 if (pcity
->server
.debug
) {
58 citizens_print(pcity
);
61 if (game
.info
.citizen_nationality
!= TRUE
) {
65 if (pcity
->nationality
== NULL
) {
66 /* If nationalities are not set (virtual cities) do nothing. */
70 delta
= city_size_get(pcity
) - citizens_count(pcity
);
73 /* No change of the city size */
79 citizens_nation_add(pcity
, plr
->slot
, delta
);
80 log_citizens_add(pcity
, delta
, plr
);
82 /* Add new citizens with the nationality of the current owner. */
83 citizens_nation_add(pcity
, city_owner(pcity
)->slot
, delta
);
84 log_citizens_add(pcity
, delta
, city_owner(pcity
));
87 /* Removed citizens. */
88 struct player_slot
*city_nations
[MAX_NUM_PLAYER_SLOTS
];
91 /* Create a list of foreign nationalities. */
92 citizens_foreign_iterate(pcity
, pslot
, nationality
) {
93 city_nations
[count
] = pslot
;
95 } citizens_foreign_iterate_end
;
97 /* First remove from foreign nationalities. */
98 while (count
> 0 && delta
< 0) {
99 int select
= fc_rand(count
);
100 struct player_slot
*pslot
= city_nations
[select
];
101 struct player
*pplayer
= player_slot_get_player(pslot
);
102 citizens nationality
= citizens_nation_get(pcity
, pslot
);
104 fc_assert_ret(nationality
!= 0);
105 fc_assert_ret(pplayer
!= NULL
);
107 if (nationality
== 1) {
108 /* Remove one citizen. */
110 citizens_nation_set(pcity
, pslot
, 0);
111 /* Remove this nation from the list of nationalities. */
112 if (select
!= count
) {
113 city_nations
[select
] = city_nations
[count
- 1];
117 log_citizens_add(pcity
, -1, pplayer
);
119 /* Get the minimal reduction = the maximum value of two negative
121 int diff
= MAX(delta
, - nationality
/ 2);
123 citizens_nation_add(pcity
, pslot
, diff
);
124 log_citizens_add(pcity
, diff
, pplayer
);
129 /* Now take the remaining citizens loss from the nation of the owner. */
130 citizens_nation_add(pcity
, city_owner(pcity
)->slot
, delta
);
131 log_citizens_add(pcity
, delta
, city_owner(pcity
));
135 fc_assert_ret(city_size_get(pcity
) == citizens_count(pcity
));
137 if (pcity
->server
.debug
) {
139 citizens_print(pcity
);
142 #undef log_citizens_add
144 /*****************************************************************************
145 Print the data about the citizens.
146 *****************************************************************************/
147 void citizens_print(const struct city
*pcity
)
149 fc_assert_ret(pcity
);
151 if (game
.info
.citizen_nationality
!= TRUE
) {
155 log_citizens("%s (size %d; %s): %d citizen(s)",
156 city_name(pcity
), city_size_get(pcity
),
157 player_name(city_owner(pcity
)), citizens_count(pcity
));
159 citizens_iterate(pcity
, pslot
, nationality
) {
160 struct player
*pplayer
= player_slot_get_player(pslot
);
162 fc_assert_ret(pplayer
!= NULL
);
164 log_citizens("%s (size %d; %s): %d citizen(s) for %s",
165 city_name(pcity
), city_size_get(pcity
),
166 player_name(city_owner(pcity
)), nationality
,
167 player_name(pplayer
));
168 } citizens_iterate_end
;
171 /*****************************************************************************
172 Return whether citizen should be converted this turn.
173 *****************************************************************************/
174 static bool citizen_convert_check(struct city
*pcity
)
176 if (fc_rand(1000) + 1 > game
.info
.citizen_convert_speed
) {
183 /*****************************************************************************
184 Convert one (random) foreign citizen to the nationality of the owner.
185 *****************************************************************************/
186 void citizens_convert(struct city
*pcity
)
188 struct player_slot
*city_nations
[MAX_NUM_PLAYER_SLOTS
], *pslot
;
189 struct player
*pplayer
;
192 fc_assert_ret(pcity
);
194 if (!game
.info
.citizen_nationality
) {
198 if (!citizen_convert_check(pcity
)) {
202 if (citizens_nation_foreign(pcity
) == 0) {
203 /* Only our own citizens. */
207 /* Create a list of foreign nationalities. */
208 citizens_foreign_iterate(pcity
, pslot
, nationality
) {
209 if (nationality
!= 0) {
210 city_nations
[count
++] = pslot
;
212 } citizens_foreign_iterate_end
;
214 /* Now convert one citizens to the city owners nationality. */
215 pslot
= city_nations
[fc_rand(count
)];
216 pplayer
= player_slot_get_player(pslot
);
218 fc_assert_ret(pplayer
!= NULL
);
220 log_citizens("%s (size %d; %s): convert 1 citizen from %s",
221 city_name(pcity
), city_size_get(pcity
),
222 player_name(city_owner(pcity
)), player_name(pplayer
));
223 citizens_nation_move(pcity
, pslot
, city_owner(pcity
)->slot
, 1);