Do not return NULL as boolean from wonder_is_lost() nor wonder_is_built()
[freeciv.git] / server / cityhand.c
blob1fb7eee8a8df051f377ba8237a48673298a96d25
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 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
22 /* utility */
23 #include "fcintl.h"
24 #include "log.h"
25 #include "rand.h"
26 #include "support.h"
28 /* common */
29 #include "city.h"
30 #include "events.h"
31 #include "game.h"
32 #include "idex.h"
33 #include "map.h"
34 #include "player.h"
35 #include "specialist.h"
36 #include "unit.h"
37 #include "worklist.h"
39 /* server */
40 #include "citytools.h"
41 #include "cityturn.h"
42 #include "notify.h"
43 #include "plrhand.h"
44 #include "sanitycheck.h"
45 #include "unithand.h"
47 #include "cityhand.h"
49 /**************************************************************************
50 Send city_name_suggestion packet back to requesting conn, with
51 suggested name and with same id which was passed in (either unit id
52 for city builder or existing city id for rename, we don't care here).
53 **************************************************************************/
54 void handle_city_name_suggestion_req(struct player *pplayer, int unit_id)
56 struct unit *punit = player_unit_by_number(pplayer, unit_id);
57 enum unit_add_build_city_result res;
59 if (NULL == punit) {
60 /* Probably died or bribed. */
61 log_verbose("handle_city_name_suggestion_req() invalid unit %d",
62 unit_id);
63 return;
66 res = unit_add_or_build_city_test(punit);
68 switch (res) {
69 case UAB_BUILD_OK:
70 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d))",
71 TILE_XY(unit_tile(punit)));
72 dlsend_packet_city_name_suggestion_info(pplayer->connections, unit_id,
73 city_name_suggestion(pplayer, unit_tile(punit)));
74 break;
76 case UAB_BAD_CITY_TERRAIN:
77 case UAB_BAD_UNIT_TERRAIN:
78 case UAB_BAD_BORDERS:
79 case UAB_NO_MIN_DIST:
80 case UAB_NOT_BUILD_UNIT:
81 case UAB_NO_MOVES_BUILD:
82 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d)): "
83 "cannot build there.", TILE_XY(unit_tile(punit)));
84 city_add_or_build_error(pplayer, punit, res); /* Message. */
85 break;
87 case UAB_ADD_OK:
88 case UAB_NOT_ADDABLE_UNIT:
89 case UAB_NO_MOVES_ADD:
90 case UAB_NOT_OWNER:
91 case UAB_TOO_BIG:
92 case UAB_NO_SPACE:
93 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d)): "
94 "there is already a city there.", TILE_XY(unit_tile(punit)));
95 /* Ignoring. */
96 break;
100 /**************************************************************************
101 Handle request to change specialist type
102 **************************************************************************/
103 void handle_city_change_specialist(struct player *pplayer, int city_id,
104 Specialist_type_id from,
105 Specialist_type_id to)
107 struct city *pcity = player_city_by_number(pplayer, city_id);
109 if (!pcity) {
110 return;
113 if (to < 0 || to >= specialist_count()
114 || from < 0 || from >= specialist_count()
115 || !city_can_use_specialist(pcity, to)
116 || pcity->specialists[from] == 0) {
117 /* This could easily just be due to clicking faster on the specialist
118 * than the server can cope with. */
119 log_verbose("Error in specialist change request from client.");
120 return;
123 pcity->specialists[from]--;
124 pcity->specialists[to]++;
126 city_refresh(pcity);
127 sanity_check_city(pcity);
128 send_city_info(pplayer, pcity);
131 /**************************************************************************
132 Handle request to change city worker in to specialist.
133 **************************************************************************/
134 void handle_city_make_specialist(struct player *pplayer, int city_id,
135 int worker_x, int worker_y)
137 struct tile *ptile;
138 struct tile *pcenter;
139 struct city *pcity = player_city_by_number(pplayer, city_id);
140 int city_radius_sq;
142 if (NULL == pcity) {
143 /* Probably lost. */
144 log_verbose("handle_city_make_specialist() bad city number %d.",
145 city_id);
146 return;
149 city_radius_sq = city_map_radius_sq_get(pcity);
150 if (!is_valid_city_coords(city_radius_sq, worker_x, worker_y)) {
151 log_error("handle_city_make_specialist() invalid city map {%d,%d} "
152 "\"%s\".", worker_x, worker_y, city_name_get(pcity));
153 return;
155 pcenter = city_tile(pcity);
157 if (NULL == (ptile = city_map_to_tile(pcenter, city_radius_sq, worker_x,
158 worker_y))) {
159 log_error("handle_city_make_specialist() unavailable city map {%d,%d} "
160 "\"%s\".", worker_x, worker_y, city_name_get(pcity));
161 return;
164 if (is_free_worked(pcity, ptile)) {
165 auto_arrange_workers(pcity);
166 } else if (tile_worked(ptile) == pcity) {
167 city_map_update_empty(pcity, ptile);
168 pcity->specialists[DEFAULT_SPECIALIST]++;
169 } else {
170 log_verbose("handle_city_make_specialist() not working {%d,%d} \"%s\".",
171 worker_x, worker_y, city_name_get(pcity));
174 city_refresh(pcity);
175 sanity_check_city(pcity);
176 sync_cities();
179 /**************************************************************************
180 Handle request to turn specialist in to city worker. Client cannot
181 tell which kind of specialist is to be taken, but this just makes worker
182 from first available specialist.
183 **************************************************************************/
184 void handle_city_make_worker(struct player *pplayer, int city_id,
185 int worker_x, int worker_y)
187 struct tile *ptile;
188 struct tile *pcenter;
189 struct city *pcity = player_city_by_number(pplayer, city_id);
190 int city_radius_sq = city_map_radius_sq_get(pcity);
192 if (NULL == pcity) {
193 /* Probably lost. */
194 log_verbose("handle_city_make_worker() bad city number %d.",city_id);
195 return;
198 if (!is_valid_city_coords(city_radius_sq, worker_x, worker_y)) {
199 log_error("handle_city_make_worker() invalid city map {%d,%d} "
200 "\"%s\".", worker_x, worker_y, city_name_get(pcity));
201 return;
203 pcenter = city_tile(pcity);
205 if (NULL == (ptile = city_map_to_tile(pcenter, city_radius_sq, worker_x,
206 worker_y))) {
207 log_error("handle_city_make_worker() unavailable city map {%d,%d} "
208 "\"%s\".", worker_x, worker_y, city_name_get(pcity));
209 return;
212 if (is_free_worked(pcity, ptile)) {
213 auto_arrange_workers(pcity);
214 sync_cities();
215 return;
218 if (tile_worked(ptile) == pcity) {
219 log_verbose("handle_city_make_worker() already working {%d,%d} \"%s\".",
220 worker_x, worker_y, city_name_get(pcity));
221 return;
224 if (0 == city_specialists(pcity)) {
225 log_verbose("handle_city_make_worker() no specialists {%d,%d} \"%s\".",
226 worker_x, worker_y, city_name_get(pcity));
227 return;
230 if (!city_can_work_tile(pcity, ptile)) {
231 log_verbose("handle_city_make_worker() cannot work here {%d,%d} \"%s\".",
232 worker_x, worker_y, city_name_get(pcity));
233 return;
236 city_map_update_worker(pcity, ptile);
238 specialist_type_iterate(i) {
239 if (pcity->specialists[i] > 0) {
240 pcity->specialists[i]--;
241 break;
243 } specialist_type_iterate_end;
245 city_refresh(pcity);
246 sanity_check_city(pcity);
247 sync_cities();
250 /**************************************************************************
251 Handle improvement selling request. Caller is responsible to validate
252 input before passing to this function if it comes from untrusted source.
253 **************************************************************************/
254 void really_handle_city_sell(struct player *pplayer, struct city *pcity,
255 struct impr_type *pimprove)
257 enum test_result sell_result;
258 int price;
260 sell_result = test_player_sell_building_now(pplayer, pcity, pimprove);
262 if (sell_result == TR_ALREADY_SOLD) {
263 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
264 _("You have already sold something here this turn."));
265 return;
268 if (sell_result != TR_SUCCESS) {
269 return;
272 pcity->did_sell=TRUE;
273 price = impr_sell_gold(pimprove);
274 notify_player(pplayer, pcity->tile, E_IMP_SOLD, ftc_server,
275 PL_("You sell %s in %s for %d gold.",
276 "You sell %s in %s for %d gold.", price),
277 improvement_name_translation(pimprove),
278 city_link(pcity), price);
279 do_sell_building(pplayer, pcity, pimprove);
281 city_refresh(pcity);
283 /* If we sold the walls the other players should see it */
284 send_city_info(NULL, pcity);
285 send_player_info_c(pplayer, pplayer->connections);
288 /**************************************************************************
289 Handle improvement selling request. This function does check its
290 parameters as they may come from untrusted source over the network.
291 **************************************************************************/
292 void handle_city_sell(struct player *pplayer, int city_id, int build_id)
294 struct city *pcity = player_city_by_number(pplayer, city_id);
295 struct impr_type *pimprove = improvement_by_number(build_id);
297 if (!pcity || !pimprove) {
298 return;
300 really_handle_city_sell(pplayer, pcity, pimprove);
303 /**************************************************************************
304 Handle buying request. Caller is responsible to validate input before
305 passing to this function if it comes from untrusted source.
306 **************************************************************************/
307 void really_handle_city_buy(struct player *pplayer, struct city *pcity)
309 int cost, total;
311 /* This function corresponds to city_can_buy() in the client. */
313 fc_assert_ret(pcity && player_owns_city(pplayer, pcity));
315 if (pcity->turn_founded == game.info.turn) {
316 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
317 _("Cannot buy in city created this turn."));
318 return;
321 if (pcity->did_buy) {
322 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
323 _("You have already bought this turn."));
324 return;
327 if (city_production_has_flag(pcity, IF_GOLD)) {
328 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
329 _("You don't buy %s!"),
330 improvement_name_translation(pcity->production.value.building));
331 return;
334 if (VUT_UTYPE == pcity->production.kind && pcity->anarchy != 0) {
335 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
336 _("Can't buy units when city is in disorder."));
337 return;
340 total = city_production_build_shield_cost(pcity);
341 cost = city_production_buy_gold_cost(pcity);
342 if (cost <= 0) {
343 return; /* sanity */
345 if (cost > pplayer->economic.gold) {
346 /* In case something changed while player tried to buy, or player
347 * tried to cheat! */
348 /* Split into two to allow localization of two pluralisations. */
349 char buf[MAX_LEN_MSG];
350 /* TRANS: This whole string is only ever used when included in one
351 * other string (search for this string to find it). */
352 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("%d gold required.",
353 "%d gold required.",
354 cost), cost);
355 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
356 /* TRANS: %s is a pre-pluralised string:
357 * "%d gold required." */
358 PL_("%s You only have %d gold.",
359 "%s You only have %d gold.", pplayer->economic.gold),
360 buf, pplayer->economic.gold);
361 return;
364 pplayer->economic.gold-=cost;
365 if (pcity->shield_stock < total){
366 /* As we never put penalty on disbanded_shields, we can
367 * fully well add the missing shields there. */
368 pcity->disbanded_shields += total - pcity->shield_stock;
369 pcity->shield_stock=total; /* AI wants this -- Syela */
370 pcity->did_buy = TRUE; /* !PS: no need to set buy flag otherwise */
372 city_refresh(pcity);
374 if (VUT_UTYPE == pcity->production.kind) {
375 notify_player(pplayer, pcity->tile, E_UNIT_BUY, ftc_server,
376 /* TRANS: bought an unit. */
377 Q_("?unit:You bought %s in %s."),
378 utype_name_translation(pcity->production.value.utype),
379 city_name_get(pcity));
380 } else if (VUT_IMPROVEMENT == pcity->production.kind) {
381 notify_player(pplayer, pcity->tile, E_IMP_BUY, ftc_server,
382 /* TRANS: bought an improvement .*/
383 Q_("?improvement:You bought %s in %s."),
384 improvement_name_translation(pcity->production.value.building),
385 city_name_get(pcity));
388 conn_list_do_buffer(pplayer->connections);
389 send_city_info(pplayer, pcity);
390 send_player_info_c(pplayer, pplayer->connections);
391 conn_list_do_unbuffer(pplayer->connections);
394 /**************************************************************************
395 Handle city worklist update request
396 **************************************************************************/
397 void handle_city_worklist(struct player *pplayer, int city_id,
398 const struct worklist *worklist)
400 struct city *pcity = player_city_by_number(pplayer, city_id);
402 if (!pcity) {
403 return;
406 worklist_copy(&pcity->worklist, worklist);
408 send_city_info(pplayer, pcity);
411 /**************************************************************************
412 Handle buying request. This function does properly check its input as
413 it may come from untrusted source over the network.
414 **************************************************************************/
415 void handle_city_buy(struct player *pplayer, int city_id)
417 struct city *pcity = player_city_by_number(pplayer, city_id);
419 if (!pcity) {
420 return;
423 really_handle_city_buy(pplayer, pcity);
426 /**************************************************************************
427 Handle city refresh request
428 **************************************************************************/
429 void handle_city_refresh(struct player *pplayer, int city_id)
431 if (city_id != 0) {
432 struct city *pcity = player_city_by_number(pplayer, city_id);
434 if (!pcity) {
435 return;
438 city_refresh(pcity);
439 send_city_info(pplayer, pcity);
440 } else {
441 city_refresh_for_player(pplayer);
445 /**************************************************************************
446 Handle request to change current production.
447 **************************************************************************/
448 void handle_city_change(struct player *pplayer, int city_id,
449 int production_kind, int production_value)
451 struct universal prod;
452 struct city *pcity = player_city_by_number(pplayer, city_id);
454 if (!universals_n_is_valid(production_kind)) {
455 log_error("[%s] bad production_kind %d.", __FUNCTION__,
456 production_kind);
457 prod.kind = VUT_NONE;
458 return;
459 } else {
460 prod = universal_by_number(production_kind, production_value);
461 if (!universals_n_is_valid(prod.kind)) {
462 log_error("[%s] production_kind %d with bad production_value %d.",
463 __FUNCTION__, production_kind, production_value);
464 prod.kind = VUT_NONE;
465 return;
469 if (!pcity) {
470 return;
473 if (are_universals_equal(&pcity->production, &prod)) {
474 /* The client probably shouldn't send such a packet. */
475 return;
478 if (!can_city_build_now(pcity, &prod)) {
479 return;
481 if (!city_can_change_build(pcity)) {
482 notify_player(pplayer, pcity->tile, E_BAD_COMMAND, ftc_server,
483 _("You have bought this turn, can't change."));
484 return;
487 change_build_target(pplayer, pcity, &prod, E_CITY_PRODUCTION_CHANGED);
489 city_refresh(pcity);
490 sanity_check_city(pcity);
491 send_city_info(pplayer, pcity);
494 /****************************************************************************
495 'struct packet_city_rename' handler.
496 ****************************************************************************/
497 void handle_city_rename(struct player *pplayer, int city_id,
498 const char *name)
500 struct city *pcity = player_city_by_number(pplayer, city_id);
501 char message[1024];
503 if (!pcity) {
504 return;
507 if (!is_allowed_city_name(pplayer, name, message, sizeof(message))) {
508 notify_player(pplayer, pcity->tile, E_BAD_COMMAND,
509 ftc_server, "%s", message);
510 return;
513 sz_strlcpy(pcity->name, name);
514 city_refresh(pcity);
515 send_city_info(NULL, pcity);
518 /****************************************************************************
519 Handles a packet from the client that requests the city options for the
520 given city be changed.
521 ****************************************************************************/
522 void handle_city_options_req(struct player *pplayer, int city_id,
523 bv_city_options options)
525 struct city *pcity = player_city_by_number(pplayer, city_id);
527 if (!pcity) {
528 return;
531 pcity->city_options = options;
533 send_city_info(pplayer, pcity);