diff -u -r freeciv/client/climisc.c freeciv.modified/client/climisc.c --- freeciv/client/climisc.c Sat Jun 12 03:44:23 1999 +++ freeciv.modified/client/climisc.c Sat Jul 10 23:58:09 1999 @@ -35,8 +35,13 @@ #include "climisc.h" +#include "city.h" +#include "packets.h" + char *tile_set_dir=NULL; +extern struct connection aconnection; + /************************************************************************** Search for the requested xpm file **************************************************************************/ @@ -235,5 +240,40 @@ freelog(LOG_NORMAL, "ran out of continent numbers in client"); ptile->continent = 0; } +} + +/************************************************************************** +Change all cities building X to building Y, if possible. +X and Y could be improvements or units; improvements are +specified by the id, units are specified by unit id + B_LAST +**************************************************************************/ +void client_change_all(int x, int y) +{ + struct packet_city_request packet; + packet.name[0]='\0'; + + city_list_iterate(game.player_ptr->cities, pcity) { + if ((!(pcity->is_building_unit) && + (pcity->currently_building == x)) || + ((pcity->is_building_unit) && + (pcity->currently_building == x-B_LAST))) { + if (y < B_LAST) { + if (can_build_improvement(pcity, x)) { + packet.city_id=pcity->id; + packet.build_id=y; + packet.is_build_id_unit_id=0; + send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE); + } + } + else { + if (can_build_unit(pcity, y-B_LAST)) { + packet.city_id=pcity->id; + packet.build_id=y-B_LAST; + packet.is_build_id_unit_id=1; + send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE); + } + } + } + } city_list_iterate_end; } diff -u -r freeciv/client/gui-gtk/cityrep.c freeciv.modified/client/gui-gtk/cityrep.c --- freeciv/client/gui-gtk/cityrep.c Sat Jun 12 03:44:24 1999 +++ freeciv.modified/client/gui-gtk/cityrep.c Sun Jul 11 01:05:28 1999 @@ -32,6 +32,7 @@ #include "optiondlg.h" #include "options.h" #include "repodlgs.h" +#include "climisc.h" #include "cityrep.h" @@ -276,16 +277,22 @@ void city_buy_callback(GtkWidget *widget, gpointer data); void city_refresh_callback(GtkWidget *widget, gpointer data); void city_change_callback(GtkWidget *widget, gpointer data); +void city_change_all_dialog_callback(GtkWidget *w, gpointer data); +void city_change_all_callback(GtkWidget *w, gpointer data); void city_list_callback(GtkWidget *w, gint row, gint column); void city_list_ucallback(GtkWidget *w, gint row, gint column); void city_config_callback(GtkWidget *widget, gpointer data); - + GtkWidget *city_dialog_shell=NULL; GtkWidget *city_label; GtkWidget *city_list; GtkWidget *city_center_command, *city_popup_command, *city_buy_command, *city_refresh_command, *city_config_command; GtkWidget *city_change_command, *city_popupmenu; +GtkWidget *city_change_all_command; +GtkWidget *city_change_all_dialog_shell; +GtkWidget *city_change_all_from_list; +GtkWidget *city_change_all_to_list; int city_dialog_shell_is_modal; @@ -439,6 +446,11 @@ gtk_signal_connect( GTK_OBJECT( city_change_command ), "event", GTK_SIGNAL_FUNC( city_change_mbutton_callback ), NULL ); + city_change_all_command = gtk_accelbutton_new("Change _All", accel); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG(city_dialog_shell)->action_area ), + city_change_all_command, TRUE, TRUE, 0 ); + GTK_WIDGET_SET_FLAGS( city_change_all_command, GTK_CAN_DEFAULT ); + city_refresh_command = gtk_accelbutton_new("_Refresh", accel); gtk_box_pack_start( GTK_BOX( GTK_DIALOG(city_dialog_shell)->action_area ), city_refresh_command, TRUE, TRUE, 0 ); @@ -461,6 +473,8 @@ GTK_SIGNAL_FUNC(city_refresh_callback), NULL); gtk_signal_connect(GTK_OBJECT(city_config_command), "clicked", GTK_SIGNAL_FUNC(city_config_callback), NULL); + gtk_signal_connect(GTK_OBJECT(city_change_all_command), "clicked", + GTK_SIGNAL_FUNC(city_change_all_callback), NULL); gtk_signal_connect(GTK_OBJECT(city_list), "select_row", GTK_SIGNAL_FUNC(city_list_callback), NULL); gtk_signal_connect(GTK_OBJECT(city_list), "unselect_row", @@ -615,6 +629,222 @@ send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE); } } + +/**************************************************************** +Handle callbacks from the "change all" dialog. +*****************************************************************/ +void city_change_all_dialog_callback(GtkWidget *w, gpointer data) +{ + GList *selection; + gint row; + int from, to; + char *cmd = (char *)data; + char buf[512]; + + if (cmd != NULL) { + if ( !( selection = GTK_CLIST( city_change_all_from_list )->selection ) ) { + sprintf(buf,"Game: Select a unit or improvement to change production from."); + append_output_window(buf); + return; + } + else { + row = (gint)selection->data; + from = (int)gtk_clist_get_row_data(GTK_CLIST(city_change_all_from_list), + row); + } + if ( !( selection = GTK_CLIST( city_change_all_to_list )->selection ) ) { + sprintf(buf,"Game: Select a unit or improvement to change production to."); + append_output_window(buf); + return; + } + else { + row = (gint)selection->data; + to = (int)gtk_clist_get_row_data(GTK_CLIST(city_change_all_to_list), + row); + } + if (from==to) { + sprintf(buf,"Game: That's the same thing!"); + append_output_window(buf); + return; + } + sprintf(buf,"Game: Changing production of every %s into %s.", + (from >= B_LAST) ? + get_unit_name(from-B_LAST) : get_improvement_name(from), + (to >= B_LAST) ? + get_unit_name(to-B_LAST) : get_improvement_name(to)); + + append_output_window(buf); + + client_change_all(from,to); + } + gtk_widget_destroy(city_change_all_dialog_shell); + city_change_all_dialog_shell = NULL; +} + +/**************************************************************** +Change all cities building one type of thing to another thing. +This is a callback for the "change all" button. +*****************************************************************/ +void city_change_all_callback(GtkWidget *w, gpointer data) +{ + GList *selection; + gint row; + struct city *pcity; + gchar *title[2][1] = {{"From:"}, + {"To:"}}; + gchar *buf[1]; + int i,j; + int *is_building; + GtkWidget *button; + GtkWidget *box; + GtkWidget *scrollpane; + + if (city_change_all_dialog_shell == NULL) { + city_change_all_dialog_shell = gtk_dialog_new(); + gtk_set_relative_position(city_dialog_shell, + city_change_all_dialog_shell, 10, 10); + + gtk_signal_connect( GTK_OBJECT(city_change_all_dialog_shell),"delete_event", + GTK_SIGNAL_FUNC(city_change_all_dialog_callback), + NULL); + + gtk_window_set_title(GTK_WINDOW(city_change_all_dialog_shell), + "Change Production Everywhere"); + + box = gtk_hbox_new(FALSE, 10); + + /* make a list of everything we're currently building */ + city_change_all_from_list = gtk_clist_new_with_titles(1, title[0]); + gtk_clist_column_titles_passive(GTK_CLIST(city_change_all_from_list)); + gtk_clist_set_selection_mode(GTK_CLIST(city_change_all_from_list), + GTK_SELECTION_SINGLE); + scrollpane = gtk_scrolled_window_new(NULL, NULL); + gtk_container_add(GTK_CONTAINER(scrollpane), + city_change_all_from_list); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrollpane ), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC ); + gtk_widget_set_usize(city_change_all_from_list, 200, 200); + + buf[0] = (char *)g_malloc(256 * sizeof(char)); + is_building = (int *)g_malloc0((B_LAST+U_LAST) * sizeof(int)); + + city_list_iterate(game.player_ptr->cities, pcity) { + if (pcity->is_building_unit) + is_building[pcity->currently_building + B_LAST] = 1; + else + is_building[pcity->currently_building] = 1; + } city_list_iterate_end; + + /* if a city was selected when "change all" was clicked on, + hilight that item so user doesn't have to click it */ + if ( ( selection = GTK_CLIST( city_list )->selection ) ) { + row = (gint)selection->data; + if((pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row))) { + if (pcity->is_building_unit) + is_building[pcity->currently_building + B_LAST] = 2; + else + is_building[pcity->currently_building] = 2; + } + } + + for(i=0; ibuild_cost); + j = gtk_clist_append(GTK_CLIST(city_change_all_to_list), buf); + gtk_clist_set_row_data(GTK_CLIST(city_change_all_to_list), + j, (gpointer)i); + } + + for(i=0; ibuild_cost); + j = gtk_clist_append(GTK_CLIST(city_change_all_to_list), buf); + gtk_clist_set_row_data(GTK_CLIST(city_change_all_to_list), + j, (gpointer)(i+B_LAST)); + } + + g_free(buf[0]); + + gtk_box_pack_start( GTK_BOX (box), + scrollpane, TRUE, TRUE, 10); + gtk_widget_show(scrollpane); + + gtk_box_pack_start( GTK_BOX (GTK_DIALOG (city_change_all_dialog_shell)->vbox), + box, TRUE, TRUE, 0); + gtk_widget_show(city_change_all_to_list); + + gtk_widget_show(box); + + button = gtk_button_new_with_label("Change"); + gtk_box_pack_start( GTK_BOX (GTK_DIALOG (city_change_all_dialog_shell)->action_area), + button, TRUE, FALSE, 0); + gtk_signal_connect( GTK_OBJECT(button),"clicked", + GTK_SIGNAL_FUNC(city_change_all_dialog_callback), + "change" ); + gtk_widget_show(button); + + button = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start( GTK_BOX (GTK_DIALOG (city_change_all_dialog_shell)->action_area), + button, TRUE, FALSE, 0); + gtk_signal_connect( GTK_OBJECT(button),"clicked", + GTK_SIGNAL_FUNC(city_change_all_dialog_callback), + NULL ); + gtk_widget_show(button); + + gtk_widget_show(city_change_all_dialog_shell); + } +} + /**************************************************************** ... diff -u -r freeciv/client/include/climisc.h freeciv.modified/client/include/climisc.h --- freeciv/client/include/climisc.h Sun Apr 25 04:38:39 1999 +++ freeciv.modified/client/include/climisc.h Sat Jul 10 22:55:02 1999 @@ -21,6 +21,7 @@ char *tilefilename(char *name); void climap_init_continents(void); void climap_update_continents(int x, int y); +void client_change_all(int x, int y); #endif /* FC__CLIMISC_H */ diff -u -r freeciv/common/city.c freeciv.modified/common/city.c --- freeciv/common/city.c Wed Jun 23 03:45:46 1999 +++ freeciv.modified/common/city.c Sat Jul 10 22:33:46 1999 @@ -852,6 +852,36 @@ return !wonder_replacement(pcity, id); } +int could_player_build_improvement(struct player *p, enum improvement_type_id id) +{ + if (!improvement_exists(id)) + return 0; + if (id == B_SSTRUCTURAL || id == B_SCOMP || id == B_SMODULE) { + if (!game.global_wonders[B_APOLLO]) { + return 0; + } else { + if (p->spaceship.state >= SSHIP_LAUNCHED) + return 0; + if (id == B_SSTRUCTURAL && p->spaceship.structurals >= NUM_SS_STRUCTURALS) + return 0; + if (id == B_SCOMP && p->spaceship.components >= NUM_SS_COMPONENTS) + return 0; + if (id == B_SMODULE && p->spaceship.modules >= NUM_SS_MODULES) + return 0; + } + } + if (is_wonder(id)) { + if (game.global_wonders[id]) return 0; + } else { + if (improvement_obsolete(p, id)) return 0; + } + return 1; +} + +/**************************************************************** +Can this improvement get built in this city, by the player +who owns the city? +*****************************************************************/ int can_build_improvement(struct city *pcity, enum improvement_type_id id) { struct player *p=city_owner(pcity); @@ -863,6 +893,19 @@ } /**************************************************************** +Can a player build this improvement somewhere? Ignores the +fact that player may not have a city with appropriate prereqs. +*****************************************************************/ +int can_player_build_improvement(struct player *p, enum improvement_type_id id) +{ + if (!improvement_exists(id)) + return 0; + if (!player_knows_improvement_tech(p,id)) + return 0; + return(could_player_build_improvement(p, id)); +} + +/**************************************************************** Whether given city can build given unit, ignoring whether unit is obsolete. *****************************************************************/ @@ -881,6 +924,22 @@ } /**************************************************************** +Whether player can build given unit somewhere, +ignoring whether unit is obsolete and assuming the +player has a coastal city. +*****************************************************************/ +int can_player_build_unit_direct(struct player *p, enum unit_type_id id) +{ + if (!unit_type_exists(id)) + return 0; + if (unit_flag(id, F_NUCLEAR) && !game.global_wonders[B_MANHATTEN]) + return 0; + if (get_invention(p,unit_types[id].tech_requirement)!=TECH_KNOWN) + return 0; + return 1; +} + +/**************************************************************** Whether given city can build given unit; returns 0 if unit is obsolete. *****************************************************************/ @@ -889,6 +948,19 @@ if (!can_build_unit_direct(pcity, id)) return 0; if (can_build_unit_direct(pcity, unit_types[id].obsoleted_by)) + return 0; + return 1; +} + +/**************************************************************** +Whether player can build given unit somewhere; +returns 0 if unit is obsolete. +*****************************************************************/ +int can_player_build_unit(struct player *p, enum unit_type_id id) +{ + if (!can_player_build_unit_direct(p, id)) + return 0; + if (can_player_build_unit_direct(p, unit_types[id].obsoleted_by)) return 0; return 1; } diff -u -r freeciv/common/city.h freeciv.modified/common/city.h --- freeciv/common/city.h Sat Jun 12 03:44:42 1999 +++ freeciv.modified/common/city.h Sat Jul 10 22:33:44 1999 @@ -208,6 +208,14 @@ enum improvement_type_id find_improvement_by_name(char *s); int improvement_variant(enum improvement_type_id id); +/* player related improvement and unit functions */ + +int could_player_build_improvement(struct player *p, enum improvement_type_id id); +int can_player_build_improvement(struct player *p, enum improvement_type_id id); +int can_player_build_unit_direct(struct player *p, enum unit_type_id id); +int can_player_build_unit(struct player *p, enum unit_type_id id); + + /* city related improvement and unit functions */ int improvement_upkeep(struct city *pcity, int i);