Freeciv-3.1
Loading...
Searching...
No Matches
citydlg_common.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19
20/* utility */
21#include "astring.h"
22#include "fcintl.h"
23#include "log.h"
24#include "support.h"
25
26/* common */
27#include "city.h"
28#include "culture.h"
29#include "game.h"
30#include "specialist.h"
31#include "unitlist.h"
32
33/* client/include */
34#include "citydlg_g.h"
35#include "mapview_g.h"
36
37/* client */
38#include "citydlg_common.h"
39#include "client_main.h" /* for can_client_issue_orders() */
40#include "climap.h"
41#include "control.h"
42#include "mapview_common.h"
43#include "options.h" /* for concise_city_production */
44#include "tilespec.h" /* for tileset_is_isometric(tileset) */
45
47
48/**********************************************************************/
52{
53 return citydlg_map_width;
54}
55
56/**********************************************************************/
60{
61 return citydlg_map_height;
62}
63
64/**********************************************************************/
68{
69 int min_x = 0, max_x = 0, min_y = 0, max_y = 0;
70 int max_rad = rs_max_city_radius_sq();
71
72 /* use maximum possible squared city radius. */
73 city_map_iterate_without_index(max_rad, city_x, city_y) {
74 float canvas_x, canvas_y;
75
77 CITY_ABS2REL(city_x), CITY_ABS2REL(city_y));
78
79 min_x = MIN(canvas_x, min_x);
80 max_x = MAX(canvas_x, max_x);
81 min_y = MIN(canvas_y, min_y);
82 max_y = MAX(canvas_y, max_y);
84
87}
88
89/**********************************************************************/
93bool city_to_canvas_pos(float *canvas_x, float *canvas_y, int city_x,
94 int city_y, int city_radius_sq)
95{
96 const int width = get_citydlg_canvas_width();
98
99 /* The citymap is centered over the center of the citydlg canvas. */
101 CITY_ABS2REL(city_y));
104
105 fc_assert_ret_val(is_valid_city_coords(city_radius_sq, city_x, city_y),
106 FALSE);
107
108 return TRUE;
109}
110
111/**********************************************************************/
115bool canvas_to_city_pos(int *city_x, int *city_y, int city_radius_sq,
116 int canvas_x, int canvas_y)
117{
118#ifdef FREECIV_DEBUG
119 int orig_canvas_x = canvas_x, orig_canvas_y = canvas_y;
120#endif
121 const int width = get_citydlg_canvas_width();
122 const int height = get_citydlg_canvas_height();
123
124 /* The citymap is centered over the center of the citydlg canvas. */
127
129 const int W = tileset_tile_width(get_tileset()),
131
132 /* Shift the tile left so the top corner of the origin tile is at
133 canvas position (0,0). */
134 canvas_x -= W / 2;
135
136 /* Perform a pi / 4 rotation, with scaling. See gui_to_map_pos()
137 for a full explanation. */
138 *city_x = DIVIDE(canvas_x * H + canvas_y * W, W * H);
139 *city_y = DIVIDE(canvas_y * W - canvas_x * H, W * H);
140 } else {
143 }
144
145 /* Add on the offset of the top-left corner to get the final
146 * coordinates (like in gui_to_map_pos() ). */
147 *city_x = CITY_REL2ABS(*city_x);
148 *city_y = CITY_REL2ABS(*city_y);
149
150 log_debug("canvas_to_city_pos(pos=(%d,%d))=(%d,%d)@radius=%d",
151 orig_canvas_x, orig_canvas_y, *city_x, *city_y, city_radius_sq);
152
153 return is_valid_city_coords(city_radius_sq, *city_x, *city_y);
154}
155
156/* Iterate over all known tiles in the city. This iteration follows the
157 * painter's algorithm and can be used for drawing. */
158#define citydlg_iterate(pcity, ptile, pedge, pcorner, _x, _y) \
159{ \
160 float _x##_0, _y##_0; \
161 int _tile_x, _tile_y; \
162 const int _x##_w = get_citydlg_canvas_width(); \
163 const int _y##_h = get_citydlg_canvas_height(); \
164 index_to_map_pos(&_tile_x, &_tile_y, tile_index((pcity)->tile)); \
165 \
166 map_to_gui_vector(tileset, 1.0, &_x##_0, &_y##_0, _tile_x, _tile_y); \
167 _x##_0 -= (_x##_w - tileset_tile_width(tileset)) / 2; \
168 _y##_0 -= (_y##_h - tileset_tile_height(tileset)) / 2; \
169 log_debug("citydlg: %f,%f + %dx%d", \
170 _x##_0, _y##_0, _x##_w, _y##_h); \
171 \
172 gui_rect_iterate_coord(_x##_0, _y##_0, _x##_w, _y##_h, \
173 ptile, pedge, pcorner, _x##_g, _y##_g, 1.0) { \
174 const int _x = _x##_g - _x##_0; \
175 const int _y = _y##_g - _y##_0; \
176 {
177
178#define citydlg_iterate_end \
179 } \
180 } gui_rect_iterate_coord_end; \
181}
182
183/**********************************************************************/
187void city_dialog_redraw_map(struct city *pcity,
188 struct canvas *pcanvas)
189{
190 struct tileset *tmp;
191
192 tmp = NULL;
193 if (unscaled_tileset) {
194 tmp = tileset;
196 }
197
198 /* First make it all black. */
199 canvas_put_rectangle(pcanvas, get_color(tileset, COLOR_MAPVIEW_UNKNOWN),
200 0, 0,
203
204 mapview_layer_iterate(layer) {
205 citydlg_iterate(pcity, ptile, pedge, pcorner, canvas_x, canvas_y) {
206 struct unit *punit
207 = ptile ? get_drawable_unit(tileset, ptile, pcity) : NULL;
208 struct city *pcity_draw = ptile ? tile_city(ptile) : NULL;
209
210 put_one_element(pcanvas, 1.0, layer, ptile, pedge, pcorner,
211 punit, pcity_draw, canvas_x, canvas_y, pcity, NULL);
214
215 if (tmp != NULL) {
216 tileset = tmp;
217 }
218}
219
220/**********************************************************************/
224char *city_production_cost_str(const struct city *pcity)
225{
226 static char cost_str[50];
228 int build_slots = city_build_slots(pcity);
229 int num_units;
230
231 if (build_slots > 1
232 && city_production_build_units(pcity, TRUE, &num_units)) {
233 /* the city could build more than one unit of the selected type */
234 if (num_units == 0) {
235 /* no unit will be finished this turn but one is build */
236 num_units++;
237 }
238
239 if (build_slots > num_units) {
240 /* some build slots for units will be unused */
241 fc_snprintf(cost_str, sizeof(cost_str), "{%d*%d}", num_units, cost);
242 } else {
243 /* maximal number of units will be build */
244 fc_snprintf(cost_str, sizeof(cost_str), "[%d*%d]", num_units, cost);
245 }
246 } else {
247 /* nothing special */
248 fc_snprintf(cost_str, sizeof(cost_str), "%3d", cost);
249 }
250
251 return cost_str;
252}
253
254/**********************************************************************/
261 char *buffer, size_t buffer_len)
262{
263 char time_str[50], *cost_str;
264 int turns, stock;
265
266 if (pcity == NULL) {
267 /*
268 * Some GUIs use this to build a "filler string" so that they can
269 * properly size the widget to hold the string. This has some
270 * obvious problems; the big one is that we have two forms of time
271 * information: "XXX turns" and "never". Later this may need to
272 * be extended to return the longer of the two; in the meantime
273 * translators can fudge it by changing this "filler" string.
274 */
275 /* TRANS: Use longer of "XXX turns" and "never" */
276 fc_strlcpy(buffer, Q_("?filler:XXX/XXX XXX turns"), buffer_len);
277
278 return;
279 }
280
281 if (city_production_has_flag(pcity, IF_GOLD)) {
282 int gold = MAX(0, pcity->surplus[O_SHIELD]);
283 fc_snprintf(buffer, buffer_len, PL_("%3d gold per turn",
284 "%3d gold per turn", gold), gold);
285 return;
286 }
287
288 turns = city_production_turns_to_build(pcity, TRUE);
289 stock = pcity->shield_stock;
290 cost_str = city_production_cost_str(pcity);
291
292 if (turns < FC_INFINITY) {
294 fc_snprintf(time_str, sizeof(time_str), "%3d", turns);
295 } else {
296 fc_snprintf(time_str, sizeof(time_str),
297 PL_("%3d turn", "%3d turns", turns), turns);
298 }
299 } else {
300 fc_snprintf(time_str, sizeof(time_str), "%s",
301 gui_options.concise_city_production ? "-" : _("never"));
302 }
303
305 fc_snprintf(buffer, buffer_len, _("%3d/%s:%s"), stock, cost_str,
306 time_str);
307 } else {
308 fc_snprintf(buffer, buffer_len, _("%3d/%s %s"), stock, cost_str,
309 time_str);
310 }
311}
312
313
314/**********************************************************************/
324void get_city_dialog_production_full(char *buffer, size_t buffer_len,
325 struct universal *target,
326 struct city *pcity)
327{
328 int turns = city_turns_to_build(pcity, target, TRUE);
329 int cost = universal_build_shield_cost(pcity, target);
330
331 switch (target->kind) {
332 case VUT_IMPROVEMENT:
333 fc_strlcpy(buffer,
335 buffer_len);
336
337 if (improvement_has_flag(target->value.building, IF_GOLD)) {
338 cat_snprintf(buffer, buffer_len, " (--) ");
339 cat_snprintf(buffer, buffer_len, _("%d/turn"),
340 MAX(0, pcity->surplus[O_SHIELD]));
341 return;
342 }
343 break;
344 default:
345 universal_name_translation(target, buffer, buffer_len);
346 break;
347 };
348 cat_snprintf(buffer, buffer_len, " (%d) ", cost);
349
350 if (turns < FC_INFINITY) {
351 cat_snprintf(buffer, buffer_len,
352 PL_("%d turn", "%d turns", turns),
353 turns);
354 } else {
355 cat_snprintf(buffer, buffer_len, _("never"));
356 }
357}
358
359/**********************************************************************/
364void get_city_dialog_production_row(char *buf[], size_t column_size,
365 struct universal *target,
366 struct city *pcity)
367{
368 struct player *pplayer = pcity ? city_owner(pcity) : client_player();
369
370 universal_name_translation(target, buf[0], column_size);
371
372 switch (target->kind) {
373 case VUT_UTYPE:
374 {
375 const struct unit_type *ptype = target->value.utype;
376
377 fc_strlcpy(buf[1], utype_values_string(ptype), column_size);
378 fc_snprintf(buf[2], column_size, "(%d)",
379 utype_build_shield_cost(pcity, pplayer, ptype));
380 break;
381 }
382 case VUT_IMPROVEMENT:
383 {
384 const struct impr_type *pimprove = target->value.building;
385
386 /* Total & turns left meaningless on capitalization */
387 if (improvement_has_flag(pimprove, IF_GOLD)) {
388 buf[1][0] = '\0';
389 fc_snprintf(buf[2], column_size, "---");
390 } else {
391 int upkeep = pcity ? city_improvement_upkeep(pcity, pimprove)
392 : pimprove->upkeep;
393 /* from city.c city_improvement_name_translation() */
394 if (pcity && is_improvement_redundant(pcity, pimprove)) {
395 fc_snprintf(buf[1], column_size, "%d*", upkeep);
396 } else {
397 const char *state = NULL;
398
399 if (is_great_wonder(pimprove)) {
400 if (improvement_obsolete(pplayer, pimprove, pcity)) {
401 state = _("Obsolete");
402 } else if (great_wonder_is_built(pimprove)) {
403 state = _("Built");
404 } else if (great_wonder_is_destroyed(pimprove)) {
405 state = _("Destroyed");
406 } else {
407 state = _("Great Wonder");
408 }
409 } else if (is_small_wonder(pimprove)) {
410 if (improvement_obsolete(pplayer, pimprove, pcity)) {
411 state = _("Obsolete");
412 } else if (wonder_is_built(pplayer, target->value.building)) {
413 state = _("Built");
414 } else {
415 state = _("Small Wonder");
416 }
417 }
418 if (state) {
419 fc_strlcpy(buf[1], state, column_size);
420 } else {
421 fc_snprintf(buf[1], column_size, "%d", upkeep);
422 }
423 }
424
425 if (pcity != NULL) {
426 fc_snprintf(buf[2], column_size, "%d",
427 impr_build_shield_cost(pcity, pimprove));
428 } else {
429 fc_snprintf(buf[2], column_size, "%d",
430 impr_estimate_build_shield_cost(pplayer, NULL, pimprove));
431 }
432 }
433 break;
434 }
435 default:
436 buf[1][0] = '\0';
437 buf[2][0] = '\0';
438 break;
439 };
440
441 /* Add the turns-to-build entry in the 4th position */
442 if (pcity) {
443 if (VUT_IMPROVEMENT == target->kind
444 && improvement_has_flag(target->value.building, IF_GOLD)) {
445 fc_snprintf(buf[3], column_size, _("%d/turn"),
446 MAX(0, pcity->surplus[O_SHIELD]));
447 } else {
448 int turns = city_turns_to_build(pcity, target, FALSE);
449
450 if (turns < FC_INFINITY) {
451 fc_snprintf(buf[3], column_size, "%d", turns);
452 } else {
453 fc_snprintf(buf[3], column_size, _("never"));
454 }
455 }
456 } else {
457 fc_snprintf(buf[3], column_size, "---");
458 }
459}
460
461/**********************************************************************/
466struct city_sum {
467 const char *format;
468 size_t n;
469 struct {
470 /* The net value that is accumulated. */
471 double value;
472 /* Description; compared for duplicate-merging.
473 * Both of these are maintained/compared until the net 'value' is known;
474 * then posdesc is used if value>=0, negdesc if value<0 */
476 /* Whether posdesc is printed for total==0 */
478 /* An auxiliary value that is also accumulated, but not tested */
479 double aux;
480 /* ...and the format string for the net aux value (appended to *desc) */
481 const char *auxfmt;
483};
484
485/**********************************************************************/
491static struct city_sum *city_sum_new(const char *format)
492{
493 struct city_sum *sum = fc_malloc(sizeof(struct city_sum));
494
495 sum->format = format;
496 sum->n = 0;
497 sum->sums = NULL;
498
499 return sum;
500}
501
502/**********************************************************************/
507static void city_sum_add_real(struct city_sum *sum, double value,
508 bool suppress_if_zero,
509 const char *auxfmt,
510 double aux,
511 char *posdesc,
512 char *negdesc)
513{
514 size_t i;
515
516 /* Likely to lead to quadratic behaviour, but who cares: */
517 for (i = 0; i < sum->n; i++) {
518 fc_assert(sum->sums != NULL);
519 if ((strcmp(sum->sums[i].posdesc, posdesc) == 0)
520 && (strcmp(sum->sums[i].negdesc, negdesc) == 0)
521 && ((sum->sums[i].auxfmt == auxfmt)
522 || (auxfmt != NULL && !strcmp(sum->sums[i].auxfmt, auxfmt)))
523 && sum->sums[i].suppress_if_zero == suppress_if_zero) {
524 /* Looks like we already have an entry like this. Accumulate values. */
525 sum->sums[i].value += value;
526 sum->sums[i].aux += aux;
529 return;
530 }
531 }
532
533 /* Didn't find description already, so add it to the end. */
534 sum->sums = fc_realloc(sum->sums, (sum->n + 1) * sizeof(sum->sums[0]));
535 sum->sums[sum->n].value = value;
536 sum->sums[sum->n].posdesc = posdesc;
537 sum->sums[sum->n].negdesc = negdesc;
539 sum->sums[sum->n].aux = aux;
540 sum->sums[sum->n].auxfmt = auxfmt;
541 sum->n++;
542}
543
544/**********************************************************************/
555static void
556 fc__attribute((__format__(__printf__, 6, 8)))
557 fc__attribute((__format__(__printf__, 7, 8)))
558 fc__attribute((nonnull (1, 6, 7)))
559 city_sum_add_full(struct city_sum *sum, double value,
560 bool suppress_if_zero,
561 const char *auxfmt,
562 double aux,
563 const char *posfmt,
564 const char *negfmt,
565 ...)
566{
567 va_list args;
568 struct astring astr = ASTRING_INIT;
569 char *posdesc, *negdesc;
570
571 /* Format both descriptions */
572 va_start(args, negfmt); /* sic -- arguments follow negfmt */
573 astr_vadd(&astr, posfmt, args);
574 posdesc = astr_to_str(&astr);
575 va_end(args);
576 va_start(args, negfmt);
577 astr_vadd(&astr, negfmt, args);
578 negdesc = astr_to_str(&astr);
579 va_end(args);
580
581 city_sum_add_real(sum, value, suppress_if_zero, auxfmt, aux,
582 posdesc, negdesc);
583}
584
585/**********************************************************************/
592static void
593 fc__attribute((__format__(__printf__, 3, 4)))
594 fc__attribute((nonnull (1, 3)))
595 city_sum_add(struct city_sum *sum, double value,
596 const char *descfmt, ...)
597{
598 va_list args;
599 struct astring astr = ASTRING_INIT;
600 char *desc;
601
602 /* Format description (same used for positive or negative net value) */
603 va_start(args, descfmt);
604 astr_vadd(&astr, descfmt, args);
605 desc = astr_to_str(&astr);
606 va_end(args);
607
608 /* Descriptions will be freed individually, so need to strdup */
609 city_sum_add_real(sum, value, FALSE, NULL, 0, desc, fc_strdup(desc));
610}
611
612/**********************************************************************/
619static void
620 fc__attribute((__format__(__printf__, 3, 4)))
621 fc__attribute((nonnull (1, 3)))
622 city_sum_add_if_nonzero(struct city_sum *sum, double value,
623 const char *descfmt, ...)
624{
625 va_list args;
626 struct astring astr = ASTRING_INIT;
627 char *desc;
628
629 /* Format description (same used for positive or negative net value) */
630 va_start(args, descfmt);
631 astr_vadd(&astr, descfmt, args);
632 desc = astr_to_str(&astr);
633 va_end(args);
634
635 /* Descriptions will be freed individually, so need to strdup */
636 city_sum_add_real(sum, value, TRUE, NULL, 0, desc, fc_strdup(desc));
637}
638
639/**********************************************************************/
642static double city_sum_total(struct city_sum *sum)
643{
644 size_t i;
645 double total = 0;
646
647 for (i = 0; i < sum->n; i++) {
648 total += sum->sums[i].value;
649 }
650 return total;
651}
652
653/**********************************************************************/
659static inline int city_sum_compare(double val1, double val2)
660{
661 /* Fudgey epsilon -- probably the numbers we're dealing with have at
662 * most 1% or 0.1% real difference */
663 if (fabs(val1-val2) < 0.0000001) {
664 return 0;
665 }
666 return (val1 > val2 ? +1 : -1);
667}
668
669/**********************************************************************/
676static void
677 fc__attribute((__format__(__printf__, 5, 6)))
678 fc__attribute((nonnull (1, 2, 5)))
679 city_sum_print(struct city_sum *sum, char *buf, size_t bufsz,
680 bool account_for_unknown,
681 const char *totalfmt, ...)
682{
683 va_list args;
684 size_t i;
685
686 /* This probably ought not to happen in well-designed rulesets, but it's
687 * possible for incomplete client knowledge to give an inaccurate
688 * breakdown. If it does happen, at least acknowledge to the user that
689 * we are confused, rather than displaying an incorrect sum. */
690 if (account_for_unknown) {
691 double total = city_sum_total(sum);
692 double actual_total;
693
694 va_start(args, totalfmt);
695 actual_total = va_arg(args, double);
696 va_end(args);
697
698 if (city_sum_compare(total, actual_total) != 0) {
699 city_sum_add(sum, actual_total - total,
700 /* TRANS: Client cannot explain some aspect of city
701 * output. Should never happen. */
702 Q_("?city_sum:(unknown)"));
703 }
704 }
705
706 for (i = 0; i < sum->n; i++) {
707 if (!sum->sums[i].suppress_if_zero
708 || city_sum_compare(sum->sums[i].value, 0) != 0) {
709 cat_snprintf(buf, bufsz,
710 sum->format, sum->sums[i].value,
711 (sum->sums[i].value < 0) ? sum->sums[i].negdesc
712 : sum->sums[i].posdesc);
713 if (sum->sums[i].auxfmt) {
714 cat_snprintf(buf, bufsz, sum->sums[i].auxfmt, sum->sums[i].aux);
715 }
716 cat_snprintf(buf, bufsz, "\n");
717 }
718 FC_FREE(sum->sums[i].posdesc);
719 FC_FREE(sum->sums[i].negdesc);
720 }
721
722 va_start(args, totalfmt);
723 fc_vsnprintf(buf + strlen(buf), bufsz - strlen(buf), totalfmt, args);
724 va_end(args);
725
726 FC_FREE(sum->sums);
727 FC_FREE(sum);
728}
729
730/**********************************************************************/
733void get_city_dialog_output_text(const struct city *pcity,
734 Output_type_id otype,
735 char *buf, size_t bufsz)
736{
737 int priority;
738 int tax[O_LAST];
739 struct output_type *output = &output_types[otype];
740 /* TRANS: format string for a row of the city output sum that adds up
741 * to "Total surplus" */
742 struct city_sum *sum = city_sum_new(Q_("?city_surplus:%+4.0f : %s"));
743
744 buf[0] = '\0';
745
746 city_sum_add(sum, pcity->citizen_base[otype],
747 Q_("?city_surplus:Citizens"));
748
749 /* Hack to get around the ugliness of add_tax_income. */
750 memset(tax, 0, O_LAST * sizeof(*tax));
751 add_tax_income(city_owner(pcity), pcity->prod[O_TRADE], tax);
752 city_sum_add_if_nonzero(sum, tax[otype],
753 Q_("?city_surplus:Taxed from trade"));
754
755 /* Special cases for "bonus" production. See set_city_production in
756 * city.c. */
757 if (otype == O_TRADE) {
758 trade_routes_iterate(pcity, proute) {
759 /* NB: (proute->value == 0) is valid case. The trade route
760 * is established but doesn't give trade surplus. */
761 struct city *trade_city = game_city_by_number(proute->partner);
762 /* TRANS: Trade partner unknown to client */
763 const char *name = trade_city ? city_name_get(trade_city) : _("(unknown)");
764 int value = proute->value
765 * (100 + get_city_bonus(pcity, EFT_TRADE_ROUTE_PCT)) / 100;
766
767 switch (proute->dir) {
768 case RDIR_BIDIRECTIONAL:
769 city_sum_add(sum, value, Q_("?city_surplus:Trading %s with %s"),
770 goods_name_translation(proute->goods),
771 name);
772 break;
773 case RDIR_FROM:
774 city_sum_add(sum, value, Q_("?city_surplus:Trading %s to %s"),
775 goods_name_translation(proute->goods),
776 name);
777 break;
778 case RDIR_TO:
779 city_sum_add(sum, value, Q_("?city_surplus:Trading %s from %s"),
780 goods_name_translation(proute->goods),
781 name);
782 break;
783 case RDIR_NONE:
784 fc_assert(proute->dir != RDIR_NONE);
785 break;
786 }
788 } else if (otype == O_GOLD) {
789 int tithes = get_city_tithes_bonus(pcity);
790
791 city_sum_add_if_nonzero(sum, tithes,
792 Q_("?city_surplus:Building tithes"));
793 }
794
795 for (priority = 0; priority < 2; priority++) {
796 enum effect_type eft[] = {EFT_OUTPUT_BONUS, EFT_OUTPUT_BONUS_2};
797
798 {
799 int base = city_sum_total(sum), bonus = 100;
800 struct effect_list *plist = effect_list_new();
801
802 (void) get_city_bonus_effects(plist, pcity, output, eft[priority]);
803
804 effect_list_iterate(plist, peffect) {
805 char buf2[512];
806 int delta;
807 int new_total;
808
809 get_effect_req_text(peffect, buf2, sizeof(buf2));
810
811 if (peffect->multiplier) {
813 peffect->multiplier);
814
815 if (mul == 0) {
816 /* Suppress text when multiplier setting suppresses effect
817 * (this will also suppress it when the city owner's policy
818 * settings are not known to us) */
819 continue;
820 }
821 delta = (peffect->value * mul) / 100;
822 } else {
823 delta = peffect->value;
824 }
825 bonus += delta;
826 new_total = bonus * base / 100;
827 city_sum_add_full(sum, new_total - city_sum_total(sum), TRUE,
828 /* TRANS: percentage city output bonus/loss from
829 * some source; preserve leading space */
830 Q_("?city_surplus: (%+.0f%%)"), delta,
831 Q_("?city_surplus:Bonus from %s"),
832 Q_("?city_surplus:Loss from %s"), buf2);
834 effect_list_destroy(plist);
835 }
836 }
837
838 if (pcity->waste[otype] != 0) {
839 int wastetypes[OLOSS_LAST];
840 bool breakdown_ok;
841 int regular_waste;
842 /* FIXME: this will give the wrong answer in rulesets with waste on
843 * taxed outputs, such as 'science waste', as our total so far includes
844 * contributions taxed from trade, whereas the equivalent bit in
845 * set_city_production() does not */
846 if (city_waste(pcity, otype, city_sum_total(sum), wastetypes)
847 == pcity->waste[otype]) {
848 /* Our calculation matches the server's, so we trust our breakdown. */
849 city_sum_add_if_nonzero(sum, -wastetypes[OLOSS_SIZE],
850 Q_("?city_surplus:Size penalty"));
851 regular_waste = wastetypes[OLOSS_WASTE];
852 breakdown_ok = TRUE;
853 } else {
854 /* Our calculation doesn't match what the server sent. Account it all
855 * to corruption/waste. */
856 regular_waste = pcity->waste[otype];
857 breakdown_ok = FALSE;
858 }
859 if (regular_waste > 0) {
860 const char *fmt;
861 switch (otype) {
862 case O_SHIELD:
863 default: /* FIXME other output types? */
864 /* TRANS: %s is normally empty, but becomes '?' if client is
865 * uncertain about its accounting (should never happen) */
866 fmt = Q_("?city_surplus:Waste%s");
867 break;
868 case O_TRADE:
869 /* TRANS: %s is normally empty, but becomes '?' if client is
870 * uncertain about its accounting (should never happen) */
871 fmt = Q_("?city_surplus:Corruption%s");
872 break;
873 }
874 city_sum_add(sum, -regular_waste, fmt, breakdown_ok ? "" : "?");
875 }
876 }
877
878 city_sum_add_if_nonzero(sum, -pcity->unhappy_penalty[otype],
879 Q_("?city_surplus:Disorder"));
880
881 if (pcity->usage[otype] > 0) {
882 city_sum_add(sum, -pcity->usage[otype],
883 Q_("?city_surplus:Used"));
884 }
885
886 city_sum_print(sum, buf, bufsz, TRUE,
887 Q_("?city_surplus:"
888 "==== : Adds up to\n"
889 "%4.0f : Total surplus"), (double) pcity->surplus[otype]);
890}
891
892/**********************************************************************/
895void get_city_dialog_illness_text(const struct city *pcity,
896 char *buf, size_t bufsz)
897{
898 int illness, ill_base, ill_size, ill_trade, ill_pollution;
899 struct effect_list *plist;
900 struct city_sum *sum;
901
902 buf[0] = '\0';
903
904 if (!game.info.illness_on) {
905 cat_snprintf(buf, bufsz, _("Illness deactivated in ruleset."));
906 return;
907 }
908
909 sum = city_sum_new(Q_("?city_plague:%+5.1f%% : %s"));
910
911 illness = city_illness_calc(pcity, &ill_base, &ill_size, &ill_trade,
912 &ill_pollution);
913
914 city_sum_add(sum, (float)(ill_size) / 10.0,
915 Q_("?city_plague:Risk from overcrowding"));
916 city_sum_add(sum, (float)(ill_trade) / 10.0,
917 Q_("?city_plague:Risk from trade"));
918 city_sum_add(sum, (float)(ill_pollution) / 10.0,
919 Q_("?city_plague:Risk from pollution"));
920
921 plist = effect_list_new();
922
923 (void) get_city_bonus_effects(plist, pcity, NULL, EFT_HEALTH_PCT);
924
925 effect_list_iterate(plist, peffect) {
926 char buf2[512];
927 int delta;
928
929 get_effect_req_text(peffect, buf2, sizeof(buf2));
930
931 if (peffect->multiplier) {
933 peffect->multiplier);
934
935 if (mul == 0) {
936 /* Suppress text when multiplier setting suppresses effect
937 * (this will also suppress it when the city owner's policy
938 * settings are not known to us) */
939 continue;
940 }
941 delta = (peffect->value * mul) / 100;
942 } else {
943 delta = peffect->value;
944 }
945
946 city_sum_add_full(sum, -(0.1 * ill_base * delta / 100), TRUE,
947 Q_("?city_plague: (%+.0f%%)"), -delta,
948 Q_("?city_plague:Risk from %s"),
949 Q_("?city_plague:Bonus from %s"), buf2);
951 effect_list_destroy(plist);
952
953 /* XXX: account_for_unknown==FALSE: the displayed sum can fail to
954 * add up due to rounding. Making it always add up probably requires
955 * arbitrary assignment of 0.1% rounding figures to particular
956 * effects with something like distribute(). */
957 city_sum_print(sum, buf, bufsz, FALSE,
958 Q_("?city_plague:"
959 "====== : Adds up to\n"
960 "%5.1f%% : Plague chance per turn"),
961 ((double)(illness) / 10.0));
962}
963
964/**********************************************************************/
967void get_city_dialog_pollution_text(const struct city *pcity,
968 char *buf, size_t bufsz)
969{
970 int pollu, prod, pop, mod;
971 struct city_sum *sum = city_sum_new(Q_("?city_pollution:%+4.0f : %s"));
972
973 /* On the server, pollution is calculated before production is deducted
974 * for disorder; we need to compensate for that */
975 pollu = city_pollution_types(pcity,
976 pcity->prod[O_SHIELD]
977 + pcity->unhappy_penalty[O_SHIELD],
978 &prod, &pop, &mod);
979 buf[0] = '\0';
980
981 city_sum_add(sum, prod, Q_("?city_pollution:Pollution from shields"));
982 city_sum_add(sum, pop, Q_("?city_pollution:Pollution from citizens"));
983 city_sum_add(sum, mod, Q_("?city_pollution:Pollution modifier"));
984 city_sum_print(sum, buf, bufsz, FALSE,
985 Q_("?city_pollution:"
986 "==== : Adds up to\n"
987 "%4.0f : Total surplus"), (double)pollu);
988}
989
990/**********************************************************************/
993void get_city_dialog_culture_text(const struct city *pcity,
994 char *buf, size_t bufsz)
995{
996 struct effect_list *plist;
997 struct city_sum *sum = city_sum_new(Q_("?city_culture:%4.0f : %s"));
998
999 buf[0] = '\0';
1000
1001 /* XXX: no way to check whether client's idea of gain/turn is accurate */
1002 city_sum_add(sum, pcity->history, Q_("?city_culture:History (%+d/turn)"),
1003 city_history_gain(pcity));
1004
1005 plist = effect_list_new();
1006
1007 (void) get_city_bonus_effects(plist, pcity, NULL, EFT_PERFORMANCE);
1008
1009 effect_list_iterate(plist, peffect) {
1010 char buf2[512];
1011 int mul = 100;
1012 int value;
1013
1014 get_effect_req_text(peffect, buf2, sizeof(buf2));
1015
1016 if (peffect->multiplier) {
1018 peffect->multiplier);
1019
1020 if (mul == 0) {
1021 /* Suppress text when multiplier setting suppresses effect
1022 * (this will also suppress it when the city owner's policy
1023 * settings are not known to us) */
1024 continue;
1025 }
1026 }
1027
1028 value = (peffect->value * mul) / 100;
1029 /* TRANS: text describing source of culture bonus ("Library+Republic") */
1030 city_sum_add_if_nonzero(sum, value, Q_("?city_culture:%s"), buf2);
1032 effect_list_destroy(plist);
1033
1034 city_sum_print(sum, buf, bufsz, TRUE,
1035 Q_("?city_culture:"
1036 "==== : Adds up to\n"
1037 "%4.0f : Total culture"), (double)pcity->client.culture);
1038}
1039
1040/**********************************************************************/
1043void get_city_dialog_airlift_text(const struct city *pcity,
1044 char *buf, size_t bufsz)
1045{
1046 char src[512];
1047 char dest[512];
1048 int unlimited = 0;
1049
1050 if ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)
1051 && (pcity->airlift >= 1 || game.info.airlift_from_always_enabled)) {
1052
1053 unlimited++;
1054
1055 /* TRANS: airlift. Possible take offs text. String is a
1056 * proviso that take offs can't occur if landings spend all the
1057 * remaining airlift when landings are limited and empty when they
1058 * aren't limited. */
1059 fc_snprintf(src, sizeof(src), _("unlimited take offs%s"),
1060 game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST
1061 /* TRANS: airlift unlimited take offs proviso used above.
1062 * Plural based on remaining airlift capacity. */
1063 ? "" : PL_(" (until the landing has been spent)",
1064 " (until all landings have been spent)",
1065 pcity->airlift));
1066 } else {
1067 fc_snprintf(src, sizeof(src),
1068 /* TRANS: airlift. Possible take offs text. Number is
1069 * airlift capacity. */
1070 PL_("%d take off", "%d take offs", pcity->airlift),
1071 pcity->airlift);
1072 }
1073
1074 if ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)
1075 && (pcity->airlift >= 1 || game.info.airlift_to_always_enabled)){
1076
1077 unlimited++;
1078
1079 /* TRANS: airlift. Possible landings text. */
1080 fc_snprintf(dest, sizeof(dest), _("unlimited landings"));
1081 } else {
1082 fc_snprintf(dest, sizeof(dest),
1083 /* TRANS: airlift. Possible landings text.
1084 * Number is airlift capacity. */
1085 PL_("%d landing", "%d landings", pcity->airlift),
1086 pcity->airlift);
1087 }
1088
1089 switch (unlimited) {
1090 case 2:
1091 /* TRANS: airlift take offs and landings */
1092 fc_snprintf(buf, bufsz, _("unlimited take offs and landings"));
1093 break;
1094 case 1:
1095 /* TRANS: airlift take offs and landings. One is unlimited. The first
1096 * string is the take offs text. The 2nd string is the landings text. */
1097 fc_snprintf(buf, bufsz, _("%s and %s"), src, dest);
1098 break;
1099 default:
1100 fc_snprintf(buf, bufsz,
1101 /* TRANS: airlift take offs or landings, no unlimited.
1102 * Number is airlift capacity. */
1103 PL_("%d take off or landing", "%d take offs or landings",
1104 pcity->airlift),
1105 pcity->airlift);
1106 break;
1107 }
1108}
1109
1110/**********************************************************************/
1113void get_city_dialog_airlift_value(const struct city *pcity,
1114 char *buf, size_t bufsz)
1115{
1116 char src[512];
1117 char dest[512];
1118 int unlimited = 0;
1119
1120 if ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)
1121 && (pcity->airlift >= 1 || game.info.airlift_from_always_enabled)) {
1122
1123 unlimited++;
1124
1125 /* TRANS: airlift. Possible take offs text. String is a symbol that
1126 * indicates that terms and conditions apply when landings are limited
1127 * and empty when they aren't limited. */
1128 fc_snprintf(src, sizeof(src), _(" ∞%s"),
1129 game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST
1130 /* TRANS: airlift unlimited take offs may be spent symbol
1131 * used above. */
1132 ? "" : _("*"));
1133 } else {
1134 /* TRANS: airlift. Possible take offs text. Number is
1135 * airlift capacity. */
1136 fc_snprintf(src, sizeof(src), _("%4d"), pcity->airlift);
1137 }
1138
1139 if ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)
1140 && (pcity->airlift >= 1 || game.info.airlift_to_always_enabled)){
1141
1142 unlimited++;
1143
1144 /* TRANS: airlift. Possible landings text. */
1145 fc_snprintf(dest, sizeof(dest), _(" ∞"));
1146 } else {
1147 /* TRANS: airlift. Possible landings text. */
1148 fc_snprintf(dest, sizeof(dest), _("%4d"), pcity->airlift);
1149 }
1150
1151 switch (unlimited) {
1152 case 2:
1153 /* TRANS: unlimited airlift take offs and landings */
1154 fc_snprintf(buf, bufsz, _(" ∞"));
1155 break;
1156 case 1:
1157 /* TRANS: airlift take offs and landings. One is unlimited. The first
1158 * string is the take offs text. The 2nd string is the landings text.
1159 * For English, initials of d)epartures and a)rrivals were chosen. */
1160 fc_snprintf(buf, bufsz, _("d: %s a: %s"), src, dest);
1161 break;
1162 default:
1163 /* TRANS: airlift take offs or landings, no unlimited */
1164 fc_snprintf(buf, bufsz, _("%s"), src);
1165 break;
1166 }
1167}
1168
1169/**********************************************************************/
1175int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx,
1176 enum citizen_category *categories)
1177{
1178 int i = 0, n;
1179
1180 fc_assert(idx >= 0 && idx < FEELING_LAST);
1181
1182 for (n = 0; n < pcity->feel[CITIZEN_HAPPY][idx]; n++, i++) {
1183 categories[i] = CITIZEN_HAPPY;
1184 }
1185 for (n = 0; n < pcity->feel[CITIZEN_CONTENT][idx]; n++, i++) {
1186 categories[i] = CITIZEN_CONTENT;
1187 }
1188 for (n = 0; n < pcity->feel[CITIZEN_UNHAPPY][idx]; n++, i++) {
1189 categories[i] = CITIZEN_UNHAPPY;
1190 }
1191 for (n = 0; n < pcity->feel[CITIZEN_ANGRY][idx]; n++, i++) {
1192 categories[i] = CITIZEN_ANGRY;
1193 }
1194
1196 for (n = 0; n < pcity->specialists[sp]; n++, i++) {
1197 categories[i] = CITIZEN_SPECIALIST + sp;
1198 }
1200
1201 if (city_size_get(pcity) != i) {
1202 log_error("get_city_citizen_types() %d citizens "
1203 "not equal %d city size in \"%s\".",
1204 i, city_size_get(pcity), city_name_get(pcity));
1205 }
1206 return i;
1207}
1208
1209/**********************************************************************/
1212void city_rotate_specialist(struct city *pcity, int citizen_index)
1213{
1214 enum citizen_category categories[MAX_CITY_SIZE];
1215 Specialist_type_id from, to;
1216 int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
1217
1218 if (citizen_index < 0 || citizen_index >= num_citizens
1219 || categories[citizen_index] < CITIZEN_SPECIALIST) {
1220 return;
1221 }
1222 from = categories[citizen_index] - CITIZEN_SPECIALIST;
1223
1224 /* Loop through all specialists in order until we find a usable one
1225 * (or run out of choices). */
1226 to = from;
1227 fc_assert(to >= 0 && to < specialist_count());
1228 do {
1229 to = (to + 1) % specialist_count();
1230 } while (to != from && !city_can_use_specialist(pcity, to));
1231
1232 if (from != to) {
1233 city_change_specialist(pcity, from, to);
1234 }
1235}
1236
1237/**********************************************************************/
1240void activate_all_units(struct tile *ptile)
1241{
1242 struct unit_list *punit_list = ptile->units;
1243 struct unit *pmyunit = NULL;
1244
1245 unit_list_iterate(punit_list, punit) {
1247 /* Activate this unit. */
1248 pmyunit = punit;
1249 request_new_unit_activity(punit, ACTIVITY_IDLE);
1250 }
1252 if (pmyunit) {
1253 /* Put the focus on one of the activated units. */
1254 unit_focus_set(pmyunit);
1255 }
1256}
1257
1258/**********************************************************************/
1261int city_change_production(struct city *pcity, struct universal *target)
1262{
1263 return dsend_packet_city_change(&client.conn, pcity->id, pcity->id,
1264 target->kind,
1265 universal_number(target));
1266}
1267
1268/**********************************************************************/
1273int city_set_worklist(struct city *pcity, const struct worklist *pworklist)
1274{
1275 return dsend_packet_city_worklist(&client.conn, pcity->id, pcity->id,
1276 pworklist);
1277}
1278
1279/**********************************************************************/
1282void city_worklist_commit(struct city *pcity, struct worklist *pwl)
1283{
1284 int k;
1285
1286 /* Update the worklist. Remember, though -- the current build
1287 target really isn't in the worklist; don't send it to the server
1288 as part of the worklist. Of course, we have to search through
1289 the current worklist to find the first _now_available_ build
1290 target (to cope with players who try mean things like adding a
1291 Battleship to a city worklist when the player doesn't even yet
1292 have the Map Making tech). */
1293
1294 for (k = 0; k < MAX_LEN_WORKLIST; k++) {
1295 int same_as_current_build;
1296 struct universal target;
1297
1298 if (!worklist_peek_ith(pwl, &target, k)) {
1299 break;
1300 }
1301
1302 same_as_current_build = are_universals_equal(&pcity->production, &target);
1303
1304 /* Very special case: If we are currently building a wonder we
1305 allow the construction to continue, even if we the wonder is
1306 finished elsewhere, ie unbuildable. */
1307 if (k == 0
1308 && VUT_IMPROVEMENT == target.kind
1309 && is_wonder(target.value.building)
1310 && same_as_current_build) {
1311 worklist_remove(pwl, k);
1312 break;
1313 }
1314
1315 /* If it can be built... */
1316 if (can_city_build_now(&(wld.map), pcity, &target)) {
1317 /* ...but we're not yet building it, then switch. */
1318 if (!same_as_current_build) {
1319 /* Change the current target */
1320 city_change_production(pcity, &target);
1321 }
1322
1323 /* This item is now (and may have always been) the current
1324 build target. Drop it out of the worklist. */
1325 worklist_remove(pwl, k);
1326 break;
1327 }
1328 }
1329
1330 /* Send the rest of the worklist on its way. */
1331 city_set_worklist(pcity, pwl);
1332}
1333
1334/**********************************************************************/
1342static bool base_city_queue_insert(struct city *pcity, int position,
1343 struct universal *item)
1344{
1345 const struct civ_map *nmap = &(wld.map);
1346
1347 if (position == 0) {
1348 struct universal old = pcity->production;
1349
1350 /* Insert as current production. */
1351 if (!can_city_build_direct(nmap, pcity, item)) {
1352 return FALSE;
1353 }
1354
1355 if (!worklist_insert(&pcity->worklist, &old, 0)) {
1356 return FALSE;
1357 }
1358
1360 } else if (position >= 1
1361 && position <= worklist_length(&pcity->worklist)) {
1362 /* Insert into middle. */
1363 if (!can_city_build_later(nmap, pcity, item)) {
1364 return FALSE;
1365 }
1366 if (!worklist_insert(&pcity->worklist, item, position - 1)) {
1367 return FALSE;
1368 }
1369 } else {
1370 /* Insert at end. */
1371 if (!can_city_build_later(nmap, pcity, item)) {
1372 return FALSE;
1373 }
1374 if (!worklist_append(&pcity->worklist, item)) {
1375 return FALSE;
1376 }
1377 }
1378 return TRUE;
1379}
1380
1381/**********************************************************************/
1386bool city_queue_insert(struct city *pcity, int position,
1387 struct universal *item)
1388{
1389 if (base_city_queue_insert(pcity, position, item)) {
1390 city_set_worklist(pcity, &pcity->worklist);
1391 return TRUE;
1392 }
1393 return FALSE;
1394}
1395
1396/**********************************************************************/
1402bool city_queue_clear(struct city *pcity)
1403{
1404 worklist_init(&pcity->worklist);
1405
1406 return TRUE;
1407}
1408
1409/**********************************************************************/
1414bool city_queue_insert_worklist(struct city *pcity, int position,
1415 const struct worklist *worklist)
1416{
1417 bool success = FALSE;
1418
1419 if (worklist_length(worklist) == 0) {
1420 return TRUE;
1421 }
1422
1423 worklist_iterate(worklist, target) {
1424 if (base_city_queue_insert(pcity, position, &target)) {
1425 if (position > 0) {
1426 /* Move to the next position (unless position == -1 in which case
1427 * we're appending. */
1428 position++;
1429 }
1430 success = TRUE;
1431 }
1433
1434 if (success) {
1435 city_set_worklist(pcity, &pcity->worklist);
1436 }
1437
1438 return success;
1439}
1440
1441/**********************************************************************/
1444void city_get_queue(struct city *pcity, struct worklist *pqueue)
1445{
1446 worklist_copy(pqueue, &pcity->worklist);
1447
1448 /* The GUI wants current production to be in the task list, but the
1449 worklist API wants it out for reasons unknown. Perhaps someone enjoyed
1450 making things more complicated than necessary? So I dance around it. */
1451
1452 /* We want the current production to be in the queue. Always. */
1453 worklist_remove(pqueue, MAX_LEN_WORKLIST - 1);
1454
1455 worklist_insert(pqueue, &pcity->production, 0);
1456}
1457
1458/**********************************************************************/
1461bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
1462{
1463 struct worklist copy;
1464 struct universal target;
1465
1466 worklist_copy(&copy, pqueue);
1467
1468 /* The GUI wants current production to be in the task list, but the
1469 worklist API wants it out for reasons unknown. Perhaps someone enjoyed
1470 making things more complicated than necessary? So I dance around it. */
1471 if (worklist_peek(&copy, &target)) {
1472
1473 if (!city_can_change_build(pcity)
1474 && !are_universals_equal(&pcity->production, &target)) {
1475 /* We cannot change production to one from worklist.
1476 * Do not replace old worklist with new one. */
1477 return FALSE;
1478 }
1479
1480 worklist_advance(&copy);
1481
1482 city_set_worklist(pcity, &copy);
1483 city_change_production(pcity, &target);
1484 } else {
1485 /* You naughty boy, you can't erase the current production. Nyah! */
1486 if (worklist_is_empty(&pcity->worklist)) {
1487 refresh_city_dialog(pcity);
1488 } else {
1489 city_set_worklist(pcity, &copy);
1490 }
1491 }
1492
1493 return TRUE;
1494}
1495
1496/**********************************************************************/
1499bool city_can_buy(const struct city *pcity)
1500{
1501 /* See really_handle_city_buy() in the server. However this function
1502 * doesn't allow for error messages. It doesn't check the cost of
1503 * buying; that's handled separately (and with an error message). */
1504 return (can_client_issue_orders()
1505 && NULL != pcity
1506 && city_owner(pcity) == client.conn.playing
1507 && pcity->turn_founded != game.info.turn
1508 && !pcity->did_buy
1509 && (VUT_UTYPE == pcity->production.kind
1510 || !improvement_has_flag(pcity->production.value.building, IF_GOLD))
1511 && !(VUT_UTYPE == pcity->production.kind
1512 && pcity->anarchy != 0)
1513 && pcity->client.buy_cost > 0);
1514}
1515
1516/**********************************************************************/
1519int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
1520{
1521 return dsend_packet_city_sell(&client.conn, pcity->id, pcity->id, sell_id);
1522}
1523
1524/**********************************************************************/
1527int city_buy_production(struct city *pcity)
1528{
1529 return dsend_packet_city_buy(&client.conn, pcity->id, pcity->id);
1530}
1531
1532/**********************************************************************/
1537{
1539 pcity->id, pcity->id, from,
1540 to);
1541}
1542
1543/**********************************************************************/
1547int city_toggle_worker(struct city *pcity, int city_x, int city_y)
1548{
1549 int city_radius_sq;
1550 struct tile *ptile;
1551
1552 if (city_owner(pcity) != client_player()) {
1553 return 0;
1554 }
1555
1556 city_radius_sq = city_map_radius_sq_get(pcity);
1557 fc_assert(is_valid_city_coords(city_radius_sq, city_x, city_y));
1558 ptile = city_map_to_tile(&(wld.map), city_tile(pcity), city_radius_sq,
1559 city_x, city_y);
1560 if (NULL == ptile) {
1561 return 0;
1562 }
1563
1564 if (NULL != tile_worked(ptile) && tile_worked(ptile) == pcity) {
1566 pcity->id, pcity->id,
1567 ptile->index);
1568 } else if (city_can_work_tile(pcity, ptile)) {
1570 pcity->id, pcity->id, ptile->index);
1571 } else {
1572 return 0;
1573 }
1574}
1575
1576/**********************************************************************/
1579int city_rename(struct city *pcity, const char *name)
1580{
1581 return dsend_packet_city_rename(&client.conn, pcity->id, pcity->id, name);
1582}
void astr_vadd(struct astring *astr, const char *format, va_list ap)
Definition astring.c:279
char * astr_to_str(struct astring *astr)
Definition astring.c:167
#define n
Definition astring.c:77
#define ASTRING_INIT
Definition astring.h:44
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
struct canvas * pcanvas
Definition canvas_g.h:42
int city_turns_to_build(const struct city *pcity, const struct universal *target, bool include_shield_stock)
Definition city.c:1938
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:658
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:722
int city_pollution_types(const struct city *pcity, int shield_total, int *pollu_prod, int *pollu_pop, int *pollu_mod)
Definition city.c:2689
int city_waste(const struct city *pcity, Output_type_id otype, int total, int *breakdown)
Definition city.c:3122
int city_build_slots(const struct city *pcity)
Definition city.c:2834
struct tile * city_map_to_tile(const struct civ_map *nmap, const struct tile *city_center, int city_radius_sq, int city_map_x, int city_map_y)
Definition city.c:300
const char * city_name_get(const struct city *pcity)
Definition city.c:1115
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1231
bool can_city_build_later(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:1009
bool city_can_use_specialist(const struct city *pcity, Specialist_type_id type)
Definition city.c:1043
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Definition city.c:712
void add_tax_income(const struct player *pplayer, int trade, int *output)
Definition city.c:2217
int get_city_tithes_bonus(const struct city *pcity)
Definition city.c:2199
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:805
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2772
bool is_valid_city_coords(const int city_radius_sq, const int city_map_x, const int city_map_y)
Definition city.c:183
bool can_city_build_direct(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:972
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:132
int rs_max_city_radius_sq(void)
Definition city.c:154
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:991
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1429
bool city_production_build_units(const struct city *pcity, bool add_production, int *num_units)
Definition city.c:732
struct output_type output_types[O_LAST]
Definition city.c:83
bool city_can_change_build(const struct city *pcity)
Definition city.c:1057
#define city_tile(_pcity_)
Definition city.h:544
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
citizen_category
Definition city.h:259
@ CITIZEN_SPECIALIST
Definition city.h:265
@ CITIZEN_ANGRY
Definition city.h:263
@ CITIZEN_HAPPY
Definition city.h:260
@ CITIZEN_CONTENT
Definition city.h:261
@ CITIZEN_UNHAPPY
Definition city.h:262
#define CITY_REL2ABS(_coor)
Definition city.h:107
#define city_owner(_pcity_)
Definition city.h:543
#define MAX_CITY_SIZE
Definition city.h:98
citizen_feeling
Definition city.h:270
@ FEELING_FINAL
Definition city.h:276
@ FEELING_LAST
Definition city.h:277
@ OLOSS_SIZE
Definition city.h:283
@ OLOSS_WASTE
Definition city.h:282
@ OLOSS_LAST
Definition city.h:284
#define city_map_iterate_without_index_end
Definition city.h:176
#define CITY_ABS2REL(_coor)
Definition city.h:108
#define city_map_iterate_without_index(_radius_sq, _x, _y)
Definition city.h:172
static double city_sum_total(struct city_sum *sum)
void get_city_dialog_production_row(char *buf[], size_t column_size, struct universal *target, struct city *pcity)
void get_city_dialog_output_text(const struct city *pcity, Output_type_id otype, char *buf, size_t bufsz)
#define citydlg_iterate_end
void get_city_dialog_production(struct city *pcity, char *buffer, size_t buffer_len)
int city_set_worklist(struct city *pcity, const struct worklist *pworklist)
int city_rename(struct city *pcity, const char *name)
void city_worklist_commit(struct city *pcity, struct worklist *pwl)
#define citydlg_iterate(pcity, ptile, pedge, pcorner, _x, _y)
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx, enum citizen_category *categories)
int city_buy_production(struct city *pcity)
char * city_production_cost_str(const struct city *pcity)
bool city_queue_insert(struct city *pcity, int position, struct universal *item)
bool city_queue_insert_worklist(struct city *pcity, int position, const struct worklist *worklist)
int city_toggle_worker(struct city *pcity, int city_x, int city_y)
void get_city_dialog_airlift_text(const struct city *pcity, char *buf, size_t bufsz)
static int city_sum_compare(double val1, double val2)
bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
int city_change_production(struct city *pcity, struct universal *target)
void get_city_dialog_production_full(char *buffer, size_t buffer_len, struct universal *target, struct city *pcity)
void city_rotate_specialist(struct city *pcity, int citizen_index)
int get_citydlg_canvas_width(void)
bool canvas_to_city_pos(int *city_x, int *city_y, int city_radius_sq, int canvas_x, int canvas_y)
static bool base_city_queue_insert(struct city *pcity, int position, struct universal *item)
void activate_all_units(struct tile *ptile)
bool city_queue_clear(struct city *pcity)
static void city_sum_add_real(struct city_sum *sum, double value, bool suppress_if_zero, const char *auxfmt, double aux, char *posdesc, char *negdesc)
void get_city_dialog_airlift_value(const struct city *pcity, char *buf, size_t bufsz)
static int citydlg_map_height
bool city_to_canvas_pos(float *canvas_x, float *canvas_y, int city_x, int city_y, int city_radius_sq)
void generate_citydlg_dimensions(void)
static struct city_sum * city_sum_new(const char *format)
void city_get_queue(struct city *pcity, struct worklist *pqueue)
void city_dialog_redraw_map(struct city *pcity, struct canvas *pcanvas)
int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
void get_city_dialog_pollution_text(const struct city *pcity, char *buf, size_t bufsz)
int city_change_specialist(struct city *pcity, Specialist_type_id from, Specialist_type_id to)
void get_city_dialog_culture_text(const struct city *pcity, char *buf, size_t bufsz)
bool city_can_buy(const struct city *pcity)
int get_citydlg_canvas_height(void)
static int citydlg_map_width
void get_city_dialog_illness_text(const struct city *pcity, char *buf, size_t bufsz)
void refresh_city_dialog(struct city *pcity)
struct civclient client
bool can_client_issue_orders(void)
#define client_player()
struct color * get_color(const struct tileset *t, enum color_std stdcolor)
void unit_focus_set(struct unit *punit)
Definition control.c:507
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Definition control.c:1854
int city_history_gain(const struct city *pcity)
Definition culture.c:37
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2840
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:789
int get_city_bonus_effects(struct effect_list *plist, const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:1075
void get_effect_req_text(const struct effect *peffect, char *buf, size_t buf_len)
Definition effects.c:1197
#define effect_list_iterate_end
Definition effects.h:375
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:373
int Impr_type_id
Definition fc_types.h:346
int Specialist_type_id
Definition fc_types.h:345
@ O_SHIELD
Definition fc_types.h:91
@ O_TRADE
Definition fc_types.h:91
@ O_GOLD
Definition fc_types.h:91
@ O_LAST
Definition fc_types.h:91
enum output_type_id Output_type_id
Definition fc_types.h:348
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:57
struct world wld
Definition game.c:58
struct city * game_city_by_number(int id)
Definition game.c:102
void canvas_put_rectangle(struct canvas *pcanvas, struct color *pcolor, int canvas_x, int canvas_y, int width, int height)
Definition canvas.c:176
static const int bufsz
Definition helpdlg.c:70
bool great_wonder_is_built(const struct impr_type *pimprove)
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_built(const struct player *pplayer, const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
bool improvement_obsolete(const struct player *pplayer, const struct impr_type *pimprove, const struct city *pcity)
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
bool is_small_wonder(const struct impr_type *pimprove)
int impr_estimate_build_shield_cost(const struct player *pplayer, const struct tile *ptile, const struct impr_type *pimprove)
const char * name
Definition inputfile.c:127
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
void map_to_gui_vector(const struct tileset *t, float zoom, float *gui_dx, float *gui_dy, int map_dx, int map_dy)
void put_one_element(struct canvas *pcanvas, float zoom, enum mapview_layer layer, const struct tile *ptile, const struct tile_edge *pedge, const struct tile_corner *pcorner, const struct unit *punit, const struct city *pcity, int canvas_x, int canvas_y, const struct city *citymode, const struct unit_type *putype)
#define H(x, y, z)
Definition md5.c:92
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
struct client_options gui_options
Definition options.c:71
int dsend_packet_city_make_worker(struct connection *pc, int city_id16, int city_id32, int tile_id)
int dsend_packet_city_sell(struct connection *pc, int city_id16, int city_id32, int build_id)
int dsend_packet_city_make_specialist(struct connection *pc, int city_id16, int city_id32, int tile_id)
int dsend_packet_city_change(struct connection *pc, int city_id16, int city_id32, int production_kind, int production_value)
int dsend_packet_city_change_specialist(struct connection *pc, int city_id16, int city_id32, Specialist_type_id from, Specialist_type_id to)
int dsend_packet_city_rename(struct connection *pc, int city_id16, int city_id32, const char *name)
int dsend_packet_city_buy(struct connection *pc, int city_id16, int city_id32)
int dsend_packet_city_worklist(struct connection *pc, int city_id16, int city_id32, const struct worklist *worklist)
int player_multiplier_effect_value(const struct player *pplayer, const struct multiplier *pmul)
Definition player.c:1933
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
int universal_number(const struct universal *source)
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
#define DIVIDE(n, d)
Definition shared.h:78
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
SPECPQ_PRIORITY_TYPE priority
Definition specpq.h:86
struct city_sum::@127 * sums
const char * auxfmt
char * posdesc
char * negdesc
const char * format
bool suppress_if_zero
Definition city.h:309
int surplus[O_LAST]
Definition city.h:343
int history
Definition city.h:393
int id
Definition city.h:315
int waste[O_LAST]
Definition city.h:344
int turn_founded
Definition city.h:372
int airlift
Definition city.h:365
int citizen_base[O_LAST]
Definition city.h:347
bool did_buy
Definition city.h:366
int anarchy
Definition city.h:370
int usage[O_LAST]
Definition city.h:348
struct worklist worklist
Definition city.h:387
struct universal production
Definition city.h:382
int bonus[O_LAST]
Definition city.h:351
int unhappy_penalty[O_LAST]
Definition city.h:345
int culture
Definition city.h:448
int buy_cost
Definition city.h:449
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition city.h:321
citizens specialists[SP_MAX]
Definition city.h:324
int shield_stock
Definition city.h:355
int prod[O_LAST]
Definition city.h:346
struct city::@17::@20 client
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
bool concise_city_production
Definition options.h:156
struct player * playing
Definition connection.h:156
Definition climisc.h:82
enum airlifting_style airlifting_style
bool airlift_from_always_enabled
bool airlift_to_always_enabled
Definition tile.h:49
int index
Definition tile.h:50
struct unit_list * units
Definition tile.h:57
Definition unit.h:138
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:896
#define fc__attribute(x)
Definition support.h:89
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_worked(_tile)
Definition tile.h:113
struct unit * get_drawable_unit(const struct tileset *t, struct tile *ptile, const struct city *citymode)
Definition tilespec.c:6302
struct tileset * get_tileset(void)
Definition tilespec.c:655
struct tileset * unscaled_tileset
Definition tilespec.c:545
bool tileset_is_isometric(const struct tileset *t)
Definition tilespec.c:675
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:728
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:716
#define mapview_layer_iterate(layer)
Definition tilespec.h:174
#define mapview_layer_iterate_end
Definition tilespec.h:182
const char * goods_name_translation(struct goods_type *pgood)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
const struct unit_type * utype
Definition fc_types.h:604
const struct impr_type * building
Definition fc_types.h:598
#define unit_owner(_pu)
Definition unit.h:394
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * utype_values_string(const struct unit_type *punittype)
Definition unittype.c:1648
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1490
void worklist_advance(struct worklist *pwl)
Definition worklist.c:104
bool worklist_peek(const struct worklist *pwl, struct universal *prod)
Definition worklist.c:76
void worklist_copy(struct worklist *dst, const struct worklist *src)
Definition worklist.c:112
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
bool worklist_peek_ith(const struct worklist *pwl, struct universal *prod, int idx)
Definition worklist.c:86
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Definition worklist.c:147
bool worklist_insert(struct worklist *pwl, const struct universal *prod, int idx)
Definition worklist.c:167
void worklist_remove(struct worklist *pwl, int idx)
Definition worklist.c:122
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57
#define worklist_iterate_end
Definition worklist.h:59
#define worklist_iterate(_list, _p)
Definition worklist.h:51
#define MAX_LEN_WORKLIST
Definition worklist.h:24