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>
35 #include "specialist.h"
40 #include "citytools.h"
44 #include "sanitycheck.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
;
60 /* Probably died or bribed. */
61 log_verbose("handle_city_name_suggestion_req() invalid unit %d",
66 res
= unit_add_or_build_city_test(punit
);
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
)));
76 case UAB_BAD_CITY_TERRAIN
:
77 case UAB_BAD_UNIT_TERRAIN
:
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. */
88 case UAB_NOT_ADDABLE_UNIT
:
89 case UAB_NO_MOVES_ADD
:
93 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d)): "
94 "there is already a city there.", TILE_XY(unit_tile(punit
)));
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
);
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.");
123 pcity
->specialists
[from
]--;
124 pcity
->specialists
[to
]++;
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
)
138 struct tile
*pcenter
;
139 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
144 log_verbose("handle_city_make_specialist() bad city number %d.",
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
));
155 pcenter
= city_tile(pcity
);
157 if (NULL
== (ptile
= city_map_to_tile(pcenter
, city_radius_sq
, worker_x
,
159 log_error("handle_city_make_specialist() unavailable city map {%d,%d} "
160 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
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
]++;
170 log_verbose("handle_city_make_specialist() not working {%d,%d} \"%s\".",
171 worker_x
, worker_y
, city_name_get(pcity
));
175 sanity_check_city(pcity
);
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
)
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
);
194 log_verbose("handle_city_make_worker() bad city number %d.",city_id
);
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
));
203 pcenter
= city_tile(pcity
);
205 if (NULL
== (ptile
= city_map_to_tile(pcenter
, city_radius_sq
, worker_x
,
207 log_error("handle_city_make_worker() unavailable city map {%d,%d} "
208 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
212 if (is_free_worked(pcity
, ptile
)) {
213 auto_arrange_workers(pcity
);
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
));
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
));
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
));
236 city_map_update_worker(pcity
, ptile
);
238 specialist_type_iterate(i
) {
239 if (pcity
->specialists
[i
] > 0) {
240 pcity
->specialists
[i
]--;
243 } specialist_type_iterate_end
;
246 sanity_check_city(pcity
);
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
;
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."));
268 if (sell_result
!= TR_SUCCESS
) {
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
);
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
) {
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
)
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."));
321 if (pcity
->did_buy
) {
322 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
323 _("You have already bought this turn."));
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
));
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."));
340 total
= city_production_build_shield_cost(pcity
);
341 cost
= city_production_buy_gold_cost(pcity
);
345 if (cost
> pplayer
->economic
.gold
) {
346 /* In case something changed while player tried to buy, or player
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.",
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
);
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 */
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
);
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
);
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
)
432 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
439 send_city_info(pplayer
, pcity
);
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__
,
457 prod
.kind
= VUT_NONE
;
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
;
473 if (are_universals_equal(&pcity
->production
, &prod
)) {
474 /* The client probably shouldn't send such a packet. */
478 if (!can_city_build_now(pcity
, &prod
)) {
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."));
487 change_build_target(pplayer
, pcity
, &prod
, E_CITY_PRODUCTION_CHANGED
);
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
,
500 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
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
);
513 sz_strlcpy(pcity
->name
, name
);
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
);
531 pcity
->city_options
= options
;
533 send_city_info(pplayer
, pcity
);