133
128
void client_remove_city(struct city *pcity)
135
130
bool effect_update;
136
struct tile *ptile = pcity->tile;
131
struct tile *ptile = city_tile(pcity);
137
132
struct city old_city = *pcity;
139
freelog(LOG_DEBUG, "removing city %s, %s, (%d %d)",
141
nation_rule_name(nation_of_city(pcity)),
134
freelog(LOG_DEBUG, "client_remove_city() %d, %s",
144
138
/* Explicitly remove all improvements, to properly remove any global effects
145
139
and to handle the preservation of "destroyed" effects. */
146
140
effect_update=FALSE;
148
built_impr_iterate(pcity, i) {
142
city_built_iterate(pcity, pimprove) {
149
143
effect_update = TRUE;
150
city_remove_improvement(pcity, i);
151
} built_impr_iterate_end;
144
city_remove_improvement(pcity, pimprove);
145
} city_built_iterate_end;
153
147
if (effect_update) {
154
148
/* nothing yet */
176
create_event(NULL, E_CITY_PRODUCTION_CHANGED,
177
_("Changing production of every %s into %s."),
179
? utype_name_translation(utype_by_number(from.value))
180
: improvement_name_translation(from.value),
182
? utype_name_translation(utype_by_number(to.value))
183
: improvement_name_translation(to.value));
170
create_event(NULL, E_CITY_PRODUCTION_CHANGED, ftc_client,
171
_("Changing production of every %s into %s."),
172
VUT_UTYPE == from.kind
173
? utype_name_translation(from.value.utype)
174
: improvement_name_translation(from.value.building),
176
? utype_name_translation(to.value.utype)
177
: improvement_name_translation(to.value.building));
185
connection_do_buffer(&aconnection);
186
city_list_iterate (game.player_ptr->cities, pcity) {
187
if (from.is_unit == pcity->production.is_unit
188
&& from.value == pcity->production.value
190
&& can_build_unit(pcity, utype_by_number(to.value)))
192
&& can_build_improvement(pcity, to.value)))) {
179
connection_do_buffer(&client.conn);
180
city_list_iterate (client.conn.playing->cities, pcity) {
181
if (are_universals_equal(&pcity->production, &from)
182
&& can_city_build_now(pcity, to)) {
193
183
last_request_id = city_change_production(pcity, to);
195
185
} city_list_iterate_end;
197
connection_do_unbuffer(&aconnection);
187
connection_do_unbuffer(&client.conn);
198
188
reports_freeze_till(last_request_id);
201
191
/***************************************************************************
192
Client variant of city_tile(). This include the case of this could a
193
ghost city (see client/packhand.c). In a such case, the returned tile
194
is an approximative position of the city on the map.
195
***************************************************************************/
196
struct tile *client_city_tile(const struct city *pcity)
206
if (NULL != city_tile(pcity)) {
207
/* Normal city case. */
208
return city_tile(pcity);
211
whole_map_iterate(ptile) {
212
if (pcity == tile_worked(ptile)) {
219
base_map_distance_vector(&dx, &dy, (int) x, (int) y,
221
x += (double) dx / num;
222
y += (double) dy / num;
225
} whole_map_iterate_end;
228
return map_pos_to_tile((int) x, (int) y);
234
/***************************************************************************
202
235
Return a string indicating one nation's embassy status with another
203
236
***************************************************************************/
204
237
const char *get_embassy_status(const struct player *me,
415
448
can_slide = FALSE;
416
449
if (get_num_units_in_focus() > 0) {
417
450
center_tile_mapcanvas(head_of_units_in_focus()->tile);
418
} else if (game.player_ptr && (pcity = find_palace(game.player_ptr))) {
451
} else if (NULL != client.conn.playing
452
&& NULL != (pcity = find_palace(client.conn.playing))) {
419
453
/* Else focus on the capital. */
420
454
center_tile_mapcanvas(pcity->tile);
421
} else if (game.player_ptr && city_list_size(game.player_ptr->cities) > 0) {
455
} else if (NULL != client.conn.playing
456
&& 0 < city_list_size(client.conn.playing->cities)) {
422
457
/* Just focus on any city. */
423
pcity = city_list_get(game.player_ptr->cities, 0);
458
pcity = city_list_get(client.conn.playing->cities, 0);
424
459
assert(pcity != NULL);
425
460
center_tile_mapcanvas(pcity->tile);
426
} else if (game.player_ptr && unit_list_size(game.player_ptr->units) > 0) {
461
} else if (NULL != client.conn.playing
462
&& 0 < unit_list_size(client.conn.playing->units)) {
427
463
/* Just focus on any unit. */
428
punit = unit_list_get(game.player_ptr->units, 0);
464
punit = unit_list_get(client.conn.playing->units, 0);
429
465
assert(punit != NULL);
430
466
center_tile_mapcanvas(punit->tile);
451
487
/****************************************************************************
452
488
Encode a CID for the target production.
453
489
****************************************************************************/
454
cid cid_encode(struct city_production target)
490
cid cid_encode(struct universal target)
456
return target.value + (target.is_unit ? B_LAST : 0);
492
return VUT_UTYPE == target.kind
493
? B_LAST + utype_number(target.value.utype)
494
: improvement_number(target.value.building);
459
497
/****************************************************************************
460
498
Encode a CID for the target unit type.
461
499
****************************************************************************/
462
cid cid_encode_unit(const struct unit_type *punittype)
500
cid cid_encode_unit(struct unit_type *punittype)
464
struct city_production target
465
= {.is_unit = TRUE, .value = punittype->index};
502
struct universal target = {
504
.value = {.utype = punittype}};
467
506
return cid_encode(target);
489
530
/**************************************************************************
490
531
Decode the CID into a city_production structure.
491
532
**************************************************************************/
492
struct city_production cid_decode(cid cid)
533
struct universal cid_decode(cid cid)
494
struct city_production target = {
495
.value = (cid >= B_LAST) ? (cid - B_LAST) : cid,
496
.is_unit = (cid >= B_LAST)
535
struct universal target;
538
target.kind = VUT_UTYPE;
539
target.value.utype = utype_by_number(cid - B_LAST);
541
target.kind = VUT_IMPROVEMENT;
542
target.value.building = improvement_by_number(cid);
502
/****************************************************************
504
*****************************************************************/
505
bool city_can_build_impr_or_unit(const struct city *pcity,
506
struct city_production target)
508
if (target.is_unit) {
509
return can_build_unit(pcity, utype_by_number(target.value));
511
return can_build_improvement(pcity, target.value);
515
548
/****************************************************************************
516
549
Return TRUE if the city supports at least one unit of the given
517
550
production type (returns FALSE if the production is a building).
518
551
****************************************************************************/
519
552
bool city_unit_supported(const struct city *pcity,
520
struct city_production target)
553
struct universal target)
522
if (target.is_unit) {
523
struct unit_type *tvtype = utype_by_number(target.value);
555
if (VUT_UTYPE == target.kind) {
556
struct unit_type *tvtype = target.value.utype;
525
558
unit_list_iterate(pcity->units_supported, punit) {
526
559
if (unit_type(punit) == tvtype)
553
586
A TestCityFunc to tell whether the item is a building and is present.
554
587
****************************************************************************/
555
588
bool city_building_present(const struct city *pcity,
556
struct city_production target)
589
struct universal target)
558
return !target.is_unit && city_got_building(pcity, target.value);
591
return VUT_IMPROVEMENT == target.kind
592
&& city_has_building(pcity, target.value.building);
561
595
/**************************************************************************
562
596
Return the numerical "section" of an item. This is used for sorting.
563
597
**************************************************************************/
564
static int target_get_section(struct city_production target)
598
static int target_get_section(struct universal target)
566
if (target.is_unit) {
567
if (utype_has_flag(utype_by_number(target.value), F_NONMIL)) {
600
if (VUT_UTYPE == target.kind) {
601
if (utype_has_flag(target.value.utype, F_CIVILIAN)) {
573
if (improvement_has_flag(target.value, IF_GOLD)) {
607
if (improvement_has_flag(target.value.building, IF_GOLD)) {
575
} else if (is_small_wonder(target.value)) {
609
} else if (is_small_wonder(target.value.building)) {
577
} else if (is_great_wonder(target.value)) {
611
} else if (is_great_wonder(target.value.building)) {
604
638
section 0: normal buildings
605
639
section 1: Capitalization
606
section 2: F_NONMIL units
640
section 2: F_CIVILIAN units
607
641
section 3: other units
608
642
section 4: small wonders
609
643
section 5: great wonders
610
644
**************************************************************************/
611
void name_and_sort_items(struct city_production *targets, int num_targets,
645
void name_and_sort_items(struct universal *targets, int num_targets,
612
646
struct item *items,
613
647
bool show_cost, struct city *pcity)
617
651
for (i = 0; i < num_targets; i++) {
618
struct city_production target = targets[i];
652
struct universal target = targets[i];
620
654
struct item *pitem = &items[i];
621
655
const char *name;
623
657
pitem->item = target;
625
if (target.is_unit) {
626
name = utype_values_translation(utype_by_number(target.value));
627
cost = unit_build_shield_cost(utype_by_number(target.value));
659
if (VUT_UTYPE == target.kind) {
660
name = utype_values_translation(target.value.utype);
661
cost = utype_build_shield_cost(target.value.utype);
629
name = get_impr_name_ex(pcity, target.value);
630
if (improvement_has_flag(target.value, IF_GOLD)) {
663
name = city_improvement_name_translation(pcity, target.value.building);
664
if (improvement_has_flag(target.value.building, IF_GOLD)) {
633
cost = impr_build_shield_cost(target.value);
667
cost = impr_build_shield_cost(target.value.building);
738
772
FIXME: this should probably take a pplayer argument.
739
773
**************************************************************************/
740
int collect_buildable_targets(struct city_production *targets)
774
int collect_buildable_targets(struct universal *targets)
742
776
int cids_used = 0;
744
if (!game.player_ptr) {
778
if (NULL == client.conn.playing) {
748
impr_type_iterate(id) {
749
if (can_player_build_improvement(game.player_ptr, id)) {
750
targets[cids_used].is_unit = FALSE;
751
targets[cids_used].value = id;
782
improvement_iterate(pimprove) {
783
if (can_player_build_improvement_now(client.conn.playing, pimprove)) {
784
targets[cids_used].kind = VUT_IMPROVEMENT;
785
targets[cids_used].value.building = pimprove;
754
} impr_type_iterate_end;
788
} improvement_iterate_end;
756
790
unit_type_iterate(punittype) {
757
if (can_player_build_unit(game.player_ptr, punittype)) {
758
targets[cids_used].is_unit = TRUE;
759
targets[cids_used].value = punittype->index;
791
if (can_player_build_unit_now(client.conn.playing, punittype)) {
792
targets[cids_used].kind = VUT_UTYPE;
793
targets[cids_used].value.utype = punittype;
762
796
} unit_type_iterate_end
771
805
FIXME: this should probably take a pplayer argument.
772
806
**************************************************************************/
773
int collect_eventually_buildable_targets(struct city_production *targets,
807
int collect_eventually_buildable_targets(struct universal *targets,
774
808
struct city *pcity,
775
809
bool advanced_tech)
777
811
int cids_used = 0;
779
if (!game.player_ptr) {
813
if (NULL == client.conn.playing) {
783
impr_type_iterate(id) {
784
bool can_build = can_player_build_improvement(game.player_ptr, id);
817
improvement_iterate(pimprove) {
818
bool can_build = can_player_build_improvement_now(client.conn.playing, pimprove);
785
819
bool can_eventually_build =
786
can_player_eventually_build_improvement(game.player_ptr, id);
820
can_player_build_improvement_later(client.conn.playing, pimprove);
788
822
/* If there's a city, can the city build the improvement? */
790
can_build = can_build && can_build_improvement(pcity, id);
824
can_build = can_build && can_city_build_improvement_now(pcity, pimprove);
791
825
can_eventually_build = can_eventually_build &&
792
can_eventually_build_improvement(pcity, id);
826
can_city_build_improvement_later(pcity, pimprove);
795
829
if ((advanced_tech && can_eventually_build) ||
796
830
(!advanced_tech && can_build)) {
797
targets[cids_used].is_unit = FALSE;
798
targets[cids_used].value = id;
831
targets[cids_used].kind = VUT_IMPROVEMENT;
832
targets[cids_used].value.building = pimprove;
801
} impr_type_iterate_end;
835
} improvement_iterate_end;
803
837
unit_type_iterate(punittype) {
804
bool can_build = can_player_build_unit(game.player_ptr, punittype);
838
bool can_build = can_player_build_unit_now(client.conn.playing, punittype);
805
839
bool can_eventually_build =
806
can_player_eventually_build_unit(game.player_ptr, punittype);
840
can_player_build_unit_later(client.conn.playing, punittype);
808
842
/* If there's a city, can the city build the unit? */
810
can_build = can_build && can_build_unit(pcity, punittype);
844
can_build = can_build && can_city_build_unit_now(pcity, punittype);
811
845
can_eventually_build = can_eventually_build &&
812
can_eventually_build_unit(pcity, punittype);
846
can_city_build_unit_later(pcity, punittype);
815
849
if ((advanced_tech && can_eventually_build) ||
816
850
(!advanced_tech && can_build)) {
817
targets[cids_used].is_unit = TRUE;
818
targets[cids_used].value = punittype->index;
851
targets[cids_used].kind = VUT_UTYPE;
852
targets[cids_used].value.utype = punittype;
821
855
} unit_type_iterate_end;
879
913
/**************************************************************************
880
Handles a chat message.
914
Handles a chat or event message.
881
915
**************************************************************************/
882
void handle_event(char *message, struct tile *ptile,
916
void handle_event(const char *featured_text, struct tile *ptile,
883
917
enum event_type event, int conn_id)
919
char plain_text[MAX_LEN_MSG];
920
struct text_tag_list *tags = text_tag_list_new();
885
921
int where = MW_OUTPUT; /* where to display the message */
922
bool fallback_needed = FALSE; /* we want fallback if actual 'where' is not
924
bool shown = FALSE; /* Message displayed somewhere at least */
887
926
if (event >= E_LAST) {
888
927
/* Server may have added a new event; leave as MW_OUTPUT */
889
freelog(LOG_NORMAL, "Unknown event type %d!", event);
928
freelog(LOG_VERBOSE, "Unknown event type %d!", event);
890
929
} else if (event >= 0) {
891
930
where = messages_where[event];
894
if (BOOL_VAL(where & MW_OUTPUT)
895
|| C_S_RUNNING != client_state()) {
896
/* When the game isn't running, the messages dialog isn't present and
897
* we want to send all messages to the chatline. There shouldn't be
898
* any problem with server spam in pregame anyway. */
899
append_output_window_full(message, conn_id);
933
/* Get the original text. */
934
featured_text_to_plain_text(featured_text, plain_text,
935
sizeof(plain_text), tags);
937
/* Display link marks when an user is pointed us something. */
939
text_tag_list_iterate(tags, ptag) {
940
if (text_tag_type(ptag) == TTT_LINK) {
941
link_mark_add_new(text_tag_link_type(ptag), text_tag_link_id(ptag));
943
} text_tag_list_iterate_end;
946
/* Maybe highlight our player and user names if someone is talking
948
if (highlight_our_names[0] != '\0'
949
&& conn_id != -1 && conn_id != client.conn.id) {
950
const char *username = client.conn.username;
951
size_t userlen = strlen(username);
952
const char *playername = ((client_player() && !client_is_observer())
953
? player_name(client_player()) : NULL);
954
size_t playerlen = playername ? strlen(playername) : 0;
957
if (playername && playername[0] == '\0') {
961
if (username && username[0] == '\0') {
965
for (p = plain_text; *p != '\0'; p++) {
967
&& 0 == mystrncasecmp(p, username, userlen)) {
968
/* Appends to be sure it will be applied at last. */
969
text_tag_list_append(tags, text_tag_new(TTT_COLOR, p - plain_text,
970
p - plain_text + userlen,
971
ft_color(NULL, highlight_our_names)));
972
} else if (playername
973
&& 0 == mystrncasecmp(p, playername, playerlen)) {
974
/* Appends to be sure it will be applied at last. */
975
text_tag_list_append(tags, text_tag_new(TTT_COLOR, p - plain_text,
976
p - plain_text + playerlen,
977
ft_color(NULL, highlight_our_names)));
983
if (BOOL_VAL(where & MW_POPUP)) {
984
/* Popups are usually not shown if player is under AI control.
985
* Server operator messages are shown always. */
986
if (NULL == client.conn.playing
987
|| !client.conn.playing->ai_data.control
988
|| event == E_MESSAGE_WALL) {
989
popup_notify_goto_dialog(_("Popup Request"), plain_text, tags, ptile);
992
/* Force to chatline so it will be visible somewhere at least.
993
* Messages window may still handle this so chatline is not needed
995
fallback_needed = TRUE;
901
1000
if (BOOL_VAL(where & MW_MESSAGES)) {
902
add_notify_window(message, ptile, event);
1001
/* When the game isn't running, the messages dialog isn't present. */
1002
if (C_S_RUNNING <= client_state()) {
1003
add_notify_window(plain_text, tags, ptile, event);
1006
/* Force to chatline instead. */
1007
fallback_needed = TRUE;
904
if (BOOL_VAL(where & MW_POPUP)
905
&& (!game.player_ptr || !game.player_ptr->ai.control)) {
906
popup_notify_goto_dialog(_("Popup Request"), message, ptile);
1012
if (BOOL_VAL(where & MW_OUTPUT) || (fallback_needed && !shown)) {
1013
output_window_event(plain_text, tags, conn_id);
909
1016
play_sound_for_event(event);
1019
text_tag_list_clear_all(tags);
1020
text_tag_list_free(tags);
912
1023
/**************************************************************************
923
1034
my_vsnprintf(message, sizeof(message), format, ap);
926
handle_event(message, ptile, event, aconnection.id);
1037
if (ft_color_requested(color)) {
1038
char colored_text[MAX_LEN_MSG];
1040
featured_text_apply_tag(message, colored_text, sizeof(colored_text),
1041
TTT_COLOR, 0, OFFSET_UNSET, color);
1042
handle_event(colored_text, ptile, event, -1);
1044
handle_event(message, ptile, event, -1);
929
1048
/**************************************************************************
931
1050
**************************************************************************/
932
1051
void write_chatline_content(const char *txt)
934
FILE *fp = fopen("civgame.log", "w"); /* should allow choice of name? */
1053
FILE *fp = fc_fopen("civgame.log", "w"); /* should allow choice of name? */
936
append_output_window(_("Exporting output window to civgame.log ..."));
1055
output_window_append(ftc_client,
1056
_("Exporting output window to civgame.log ..."));
940
append_output_window(_("Export complete."));
1060
output_window_append(ftc_client, _("Export complete."));
942
append_output_window(_("Export failed, couldn't write to file."));
1062
output_window_append(ftc_client,
1063
_("Export failed, couldn't write to file."));
1034
1155
**************************************************************************/
1035
1156
void cityrep_buy(struct city *pcity)
1037
int value = city_buy_cost(pcity);
1039
if (!pcity->production.is_unit
1040
&& improvement_has_flag(pcity->production.value, IF_GOLD)) {
1041
create_event(pcity->tile, E_BAD_COMMAND,
1042
_("You don't buy %s in %s!"),
1043
improvement_name_translation(pcity->production.value),
1160
if (city_production_has_flag(pcity, IF_GOLD)) {
1161
create_event(pcity->tile, E_BAD_COMMAND, ftc_client,
1162
_("You don't buy %s in %s!"),
1163
improvement_name_translation(pcity->production.value.building),
1167
value = city_production_buy_gold_cost(pcity);
1048
1169
if (city_owner(pcity)->economic.gold >= value) {
1049
1170
city_buy_production(pcity);
1053
if (pcity->production.is_unit) {
1054
name = utype_name_translation(utype_by_number(pcity->production.value));
1056
name = get_impr_name_ex(pcity, pcity->production.value);
1059
create_event(NULL, E_BAD_COMMAND,
1060
_("%s costs %d gold and you only have %d gold."),
1061
name, value, city_owner(pcity)->economic.gold);
1172
create_event(NULL, E_BAD_COMMAND, ftc_client,
1173
_("%s costs %d gold and you only have %d gold."),
1174
city_production_name_translation(pcity),
1176
city_owner(pcity)->economic.gold);
1111
1226
/****************************************************************************
1227
Determines which color type should be used for unit background.
1228
This is only guesswork based on unit properties. One should not
1229
take UNIT_BG_FLYING seriously meaning that unit can fly - custom
1230
ruleset might have units with similar properties but explains these
1231
properties by some other means than by flying.
1232
****************************************************************************/
1233
enum unit_bg_color_type unit_color_type(const struct unit_type *punittype)
1235
struct unit_class *pclass = utype_class(punittype);
1237
if (pclass->hp_loss_pct > 0) {
1238
return UNIT_BG_HP_LOSS;
1241
if (pclass->move_type == LAND_MOVING) {
1242
return UNIT_BG_LAND;
1244
if (pclass->move_type == SEA_MOVING) {
1248
assert(pclass->move_type == BOTH_MOVING);
1250
if (uclass_has_flag(pclass, UCF_TERRAIN_SPEED)) {
1251
/* Unit moves on both sea and land by speed determined by terrain */
1252
return UNIT_BG_AMPHIBIOUS;
1255
return UNIT_BG_FLYING;
1258
/****************************************************************************
1112
1259
Comparison function used by qsort in buy_production_in_selected_cities().
1113
1260
****************************************************************************/
1114
1261
static int city_buy_cost_compare(const void *a, const void *b)