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 city_build_result res
;
60 /* Probably died or bribed. */
61 log_verbose("handle_city_name_suggestion_req() invalid unit %d",
66 if (action_prob_possible(action_prob_vs_tile(punit
, ACTION_FOUND_CITY
,
68 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d))",
69 TILE_XY(unit_tile(punit
)));
70 dlsend_packet_city_name_suggestion_info(pplayer
->connections
, unit_id
,
71 city_name_suggestion(pplayer
, unit_tile(punit
)));
73 /* The rest of this function is error handling. */
77 res
= city_build_here_test(unit_tile(punit
), punit
);
81 /* No action enabler permitted the city to be built. */
82 case CB_BAD_CITY_TERRAIN
:
83 case CB_BAD_UNIT_TERRAIN
:
86 log_verbose("handle_city_name_suggest_req(unit_pos (%d, %d)): "
87 "cannot build there.", TILE_XY(unit_tile(punit
)));
89 illegal_action_msg(pplayer
, E_BAD_COMMAND
, punit
, ACTION_FOUND_CITY
,
90 unit_tile(punit
), NULL
, NULL
);
95 /**************************************************************************
96 Handle request to change specialist type
97 **************************************************************************/
98 void handle_city_change_specialist(struct player
*pplayer
, int city_id
,
99 Specialist_type_id from
,
100 Specialist_type_id to
)
102 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
108 if (to
< 0 || to
>= specialist_count()
109 || from
< 0 || from
>= specialist_count()
110 || !city_can_use_specialist(pcity
, to
)
111 || pcity
->specialists
[from
] == 0) {
112 /* This could easily just be due to clicking faster on the specialist
113 * than the server can cope with. */
114 log_verbose("Error in specialist change request from client.");
118 pcity
->specialists
[from
]--;
119 pcity
->specialists
[to
]++;
122 sanity_check_city(pcity
);
123 send_city_info(pplayer
, pcity
);
126 /**************************************************************************
127 Handle request to change city worker in to specialist.
128 **************************************************************************/
129 void handle_city_make_specialist(struct player
*pplayer
, int city_id
,
130 int worker_x
, int worker_y
)
133 struct tile
*pcenter
;
134 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
139 log_verbose("handle_city_make_specialist() bad city number %d.",
144 city_radius_sq
= city_map_radius_sq_get(pcity
);
145 if (!is_valid_city_coords(city_radius_sq
, worker_x
, worker_y
)) {
146 log_error("handle_city_make_specialist() invalid city map {%d,%d} "
147 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
150 pcenter
= city_tile(pcity
);
152 if (NULL
== (ptile
= city_map_to_tile(pcenter
, city_radius_sq
, worker_x
,
154 log_error("handle_city_make_specialist() unavailable city map {%d,%d} "
155 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
159 if (is_free_worked(pcity
, ptile
)) {
160 auto_arrange_workers(pcity
);
161 } else if (tile_worked(ptile
) == pcity
) {
162 city_map_update_empty(pcity
, ptile
);
163 pcity
->specialists
[DEFAULT_SPECIALIST
]++;
165 log_verbose("handle_city_make_specialist() not working {%d,%d} \"%s\".",
166 worker_x
, worker_y
, city_name_get(pcity
));
170 sanity_check_city(pcity
);
174 /**************************************************************************
175 Handle request to turn specialist in to city worker. Client cannot
176 tell which kind of specialist is to be taken, but this just makes worker
177 from first available specialist.
178 **************************************************************************/
179 void handle_city_make_worker(struct player
*pplayer
, int city_id
,
180 int worker_x
, int worker_y
)
183 struct tile
*pcenter
;
184 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
185 int city_radius_sq
= city_map_radius_sq_get(pcity
);
189 log_verbose("handle_city_make_worker() bad city number %d.",city_id
);
193 if (!is_valid_city_coords(city_radius_sq
, worker_x
, worker_y
)) {
194 log_error("handle_city_make_worker() invalid city map {%d,%d} "
195 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
198 pcenter
= city_tile(pcity
);
200 if (NULL
== (ptile
= city_map_to_tile(pcenter
, city_radius_sq
, worker_x
,
202 log_error("handle_city_make_worker() unavailable city map {%d,%d} "
203 "\"%s\".", worker_x
, worker_y
, city_name_get(pcity
));
207 if (is_free_worked(pcity
, ptile
)) {
208 auto_arrange_workers(pcity
);
213 if (tile_worked(ptile
) == pcity
) {
214 log_verbose("handle_city_make_worker() already working {%d,%d} \"%s\".",
215 worker_x
, worker_y
, city_name_get(pcity
));
219 if (0 == city_specialists(pcity
)) {
220 log_verbose("handle_city_make_worker() no specialists {%d,%d} \"%s\".",
221 worker_x
, worker_y
, city_name_get(pcity
));
225 if (!city_can_work_tile(pcity
, ptile
)) {
226 log_verbose("handle_city_make_worker() cannot work here {%d,%d} \"%s\".",
227 worker_x
, worker_y
, city_name_get(pcity
));
231 city_map_update_worker(pcity
, ptile
);
233 specialist_type_iterate(i
) {
234 if (pcity
->specialists
[i
] > 0) {
235 pcity
->specialists
[i
]--;
238 } specialist_type_iterate_end
;
241 sanity_check_city(pcity
);
245 /**************************************************************************
246 Handle improvement selling request. Caller is responsible to validate
247 input before passing to this function if it comes from untrusted source.
248 **************************************************************************/
249 void really_handle_city_sell(struct player
*pplayer
, struct city
*pcity
,
250 struct impr_type
*pimprove
)
252 enum test_result sell_result
;
255 sell_result
= test_player_sell_building_now(pplayer
, pcity
, pimprove
);
257 if (sell_result
== TR_ALREADY_SOLD
) {
258 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
259 _("You have already sold something here this turn."));
263 if (sell_result
!= TR_SUCCESS
) {
267 pcity
->did_sell
=TRUE
;
268 price
= impr_sell_gold(pimprove
);
269 notify_player(pplayer
, pcity
->tile
, E_IMP_SOLD
, ftc_server
,
270 PL_("You sell %s in %s for %d gold.",
271 "You sell %s in %s for %d gold.", price
),
272 improvement_name_translation(pimprove
),
273 city_link(pcity
), price
);
274 do_sell_building(pplayer
, pcity
, pimprove
);
278 /* If we sold the walls the other players should see it */
279 send_city_info(NULL
, pcity
);
280 send_player_info_c(pplayer
, pplayer
->connections
);
283 /**************************************************************************
284 Handle improvement selling request. This function does check its
285 parameters as they may come from untrusted source over the network.
286 **************************************************************************/
287 void handle_city_sell(struct player
*pplayer
, int city_id
, int build_id
)
289 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
290 struct impr_type
*pimprove
= improvement_by_number(build_id
);
292 if (!pcity
|| !pimprove
) {
295 really_handle_city_sell(pplayer
, pcity
, pimprove
);
298 /**************************************************************************
299 Handle buying request. Caller is responsible to validate input before
300 passing to this function if it comes from untrusted source.
301 **************************************************************************/
302 void really_handle_city_buy(struct player
*pplayer
, struct city
*pcity
)
306 /* This function corresponds to city_can_buy() in the client. */
308 fc_assert_ret(pcity
&& player_owns_city(pplayer
, pcity
));
310 if (pcity
->turn_founded
== game
.info
.turn
) {
311 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
312 _("Cannot buy in city created this turn."));
316 if (pcity
->did_buy
) {
317 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
318 _("You have already bought this turn."));
322 if (city_production_has_flag(pcity
, IF_GOLD
)) {
323 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
324 _("You don't buy %s!"),
325 improvement_name_translation(pcity
->production
.value
.building
));
329 if (VUT_UTYPE
== pcity
->production
.kind
&& pcity
->anarchy
!= 0) {
330 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
331 _("Can't buy units when city is in disorder."));
335 total
= city_production_build_shield_cost(pcity
);
336 cost
= city_production_buy_gold_cost(pcity
);
340 if (cost
> pplayer
->economic
.gold
) {
341 /* In case something changed while player tried to buy, or player
343 /* Split into two to allow localization of two pluralisations. */
344 char buf
[MAX_LEN_MSG
];
345 /* TRANS: This whole string is only ever used when included in one
346 * other string (search for this string to find it). */
347 fc_snprintf(buf
, ARRAY_SIZE(buf
), PL_("%d gold required.",
350 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
351 /* TRANS: %s is a pre-pluralised string:
352 * "%d gold required." */
353 PL_("%s You only have %d gold.",
354 "%s You only have %d gold.", pplayer
->economic
.gold
),
355 buf
, pplayer
->economic
.gold
);
359 pplayer
->economic
.gold
-=cost
;
360 if (pcity
->shield_stock
< total
){
361 /* As we never put penalty on disbanded_shields, we can
362 * fully well add the missing shields there. */
363 pcity
->disbanded_shields
+= total
- pcity
->shield_stock
;
364 pcity
->shield_stock
=total
; /* AI wants this -- Syela */
365 pcity
->did_buy
= TRUE
; /* !PS: no need to set buy flag otherwise */
369 if (VUT_UTYPE
== pcity
->production
.kind
) {
370 notify_player(pplayer
, pcity
->tile
, E_UNIT_BUY
, ftc_server
,
371 /* TRANS: bought an unit. */
372 Q_("?unit:You bought %s in %s."),
373 utype_name_translation(pcity
->production
.value
.utype
),
374 city_name_get(pcity
));
375 } else if (VUT_IMPROVEMENT
== pcity
->production
.kind
) {
376 notify_player(pplayer
, pcity
->tile
, E_IMP_BUY
, ftc_server
,
377 /* TRANS: bought an improvement .*/
378 Q_("?improvement:You bought %s in %s."),
379 improvement_name_translation(pcity
->production
.value
.building
),
380 city_name_get(pcity
));
383 conn_list_do_buffer(pplayer
->connections
);
384 send_city_info(pplayer
, pcity
);
385 send_player_info_c(pplayer
, pplayer
->connections
);
386 conn_list_do_unbuffer(pplayer
->connections
);
389 /**************************************************************************
390 Handle city worklist update request
391 **************************************************************************/
392 void handle_city_worklist(struct player
*pplayer
, int city_id
,
393 const struct worklist
*worklist
)
395 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
401 worklist_copy(&pcity
->worklist
, worklist
);
403 send_city_info(pplayer
, pcity
);
406 /**************************************************************************
407 Handle buying request. This function does properly check its input as
408 it may come from untrusted source over the network.
409 **************************************************************************/
410 void handle_city_buy(struct player
*pplayer
, int city_id
)
412 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
418 really_handle_city_buy(pplayer
, pcity
);
421 /**************************************************************************
422 Handle city refresh request
423 **************************************************************************/
424 void handle_city_refresh(struct player
*pplayer
, int city_id
)
427 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
434 send_city_info(pplayer
, pcity
);
436 city_refresh_for_player(pplayer
);
440 /**************************************************************************
441 Handle request to change current production.
442 **************************************************************************/
443 void handle_city_change(struct player
*pplayer
, int city_id
,
444 int production_kind
, int production_value
)
446 struct universal prod
;
447 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
449 if (!universals_n_is_valid(production_kind
)) {
450 log_error("[%s] bad production_kind %d.", __FUNCTION__
,
452 prod
.kind
= VUT_NONE
;
455 prod
= universal_by_number(production_kind
, production_value
);
456 if (!universals_n_is_valid(prod
.kind
)) {
457 log_error("[%s] production_kind %d with bad production_value %d.",
458 __FUNCTION__
, production_kind
, production_value
);
459 prod
.kind
= VUT_NONE
;
468 if (are_universals_equal(&pcity
->production
, &prod
)) {
469 /* The client probably shouldn't send such a packet. */
473 if (!can_city_build_now(pcity
, &prod
)) {
476 if (!city_can_change_build(pcity
)) {
477 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
, ftc_server
,
478 _("You have bought this turn, can't change."));
482 change_build_target(pplayer
, pcity
, &prod
, E_CITY_PRODUCTION_CHANGED
);
485 sanity_check_city(pcity
);
486 send_city_info(pplayer
, pcity
);
489 /****************************************************************************
490 'struct packet_city_rename' handler.
491 ****************************************************************************/
492 void handle_city_rename(struct player
*pplayer
, int city_id
,
495 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
502 if (!is_allowed_city_name(pplayer
, name
, message
, sizeof(message
))) {
503 notify_player(pplayer
, pcity
->tile
, E_BAD_COMMAND
,
504 ftc_server
, "%s", message
);
508 sz_strlcpy(pcity
->name
, name
);
510 send_city_info(NULL
, pcity
);
513 /****************************************************************************
514 Handles a packet from the client that requests the city options for the
515 given city be changed.
516 ****************************************************************************/
517 void handle_city_options_req(struct player
*pplayer
, int city_id
,
518 bv_city_options options
)
520 struct city
*pcity
= player_city_by_number(pplayer
, city_id
);
526 pcity
->city_options
= options
;
528 send_city_info(pplayer
, pcity
);