[Freeciv-Dev] rewrite of upgrade wrapper code (PR#6735)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=6735 >
Here is the actual patch. See the previous RT discussion for explanation.
Raimar: I disagree about the split of need_city/need_gold. If this is
ever generalized in future it will be no problem to change this code.
However I am dubious that this will happen, and in the meantime the
extra parameter gives the function unneeded complexity IMO.
Untested.
jason
Index: client/gui-gtk/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/citydlg.c,v
retrieving revision 1.174
diff -u -r1.174 citydlg.c
--- client/gui-gtk/citydlg.c 2003/11/28 17:37:19 1.174
+++ client/gui-gtk/citydlg.c 2003/12/22 02:02:07
@@ -2688,48 +2688,25 @@
*****************************************************************/
static void unit_upgrade_callback(gpointer data)
{
- struct unit *punit;
+ struct unit *punit = player_find_unit_by_id(game.player_ptr, (size_t) data);
char buf[512];
- int ut1, ut2;
- int value;
- if ((punit = player_find_unit_by_id(game.player_ptr, (size_t) data))) {
- ut1 = punit->type;
- ut2 = can_upgrade_unittype(game.player_ptr, ut1);
+ if (!punit) {
+ return;
+ }
- if (ut2 == -1) {
- /* this shouldn't generally happen, but it is conceivable */
- my_snprintf(buf, sizeof(buf),
- _("Sorry: cannot upgrade %s."), unit_types[ut1].name);
- popup_message_dialog(top_vbox,
- _("Upgrade Unit!"), buf,
- dummy_close_callback, NULL,
- _("Darn"), NULL, 0, NULL);
- } else {
- value = unit_upgrade_price(game.player_ptr, ut1, ut2);
-
- if (game.player_ptr->economic.gold >= value) {
- my_snprintf(buf, sizeof(buf), _("Upgrade %s to %s for %d gold?\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- popup_message_dialog(top_vbox,
- _("Upgrade Obsolete Units"), buf,
- dummy_close_callback, NULL,
- _("_Yes"), unit_upgrade_callback_yes,
- GINT_TO_POINTER(punit->id), _("_No"),
- NULL, 0, NULL);
- } else {
- my_snprintf(buf, sizeof(buf),
- _("Upgrading %s to %s costs %d gold.\n"
- "Treasury contains %d gold."), unit_types[ut1].name,
- unit_types[ut2].name, value,
- game.player_ptr->economic.gold);
- popup_message_dialog(top_vbox,_("Upgrade Unit!"),buf,
- dummy_close_callback, NULL,
- _("Darn"), NULL, 0, NULL);
- }
- }
+ if (get_unit_upgrade_info(buf, sizeof(buf), punit) == UR_OK) {
+ popup_message_dialog(top_vbox,
+ _("Upgrade Obsolete Units"), buf,
+ dummy_close_callback, NULL,
+ _("_Yes"), unit_upgrade_callback_yes,
+ GINT_TO_POINTER(punit->id), _("_No"),
+ NULL, 0, NULL);
+ } else {
+ popup_message_dialog(top_vbox,
+ _("Upgrade Unit!"), buf,
+ dummy_close_callback, NULL,
+ _("Darn"), NULL, 0, NULL);
}
}
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/citydlg.c,v
retrieving revision 1.67
diff -u -r1.67 citydlg.c
--- client/gui-gtk-2.0/citydlg.c 2003/11/28 17:37:20 1.67
+++ client/gui-gtk-2.0/citydlg.c 2003/12/22 02:02:07
@@ -2206,71 +2206,41 @@
*****************************************************************/
static void unit_upgrade_callback(GtkWidget *w, gpointer data)
{
- struct unit *punit;
- int ut1, ut2;
- int value;
+ struct unit *punit = player_find_unit_by_id(game.player_ptr,
+ (size_t) data);
GtkWidget *shell;
+ char buf[512];
- if ((punit = player_find_unit_by_id(game.player_ptr, (size_t) data))) {
- ut1 = punit->type;
- ut2 = can_upgrade_unittype(game.player_ptr, ut1);
-
- if (ut2 == -1) {
- /* this shouldn't generally happen, but it is conceivable */
- shell = gtk_message_dialog_new(NULL,
- 0,
- GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
- _("Sorry: cannot upgrade %s."), unit_types[ut1].name);
-
- gtk_window_set_title(GTK_WINDOW(shell), _("Upgrade Unit!"));
- if (dialogs_on_top) {
- gtk_window_set_transient_for(GTK_WINDOW(shell),
- GTK_WINDOW(toplevel));
- }
- g_signal_connect(shell, "response", G_CALLBACK(gtk_widget_destroy),
- NULL);
- gtk_window_present(GTK_WINDOW(shell));
- } else {
- value = unit_upgrade_price(game.player_ptr, ut1, ut2);
-
- if (game.player_ptr->economic.gold >= value) {
- shell = gtk_message_dialog_new(NULL,
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
- _("Upgrade %s to %s for %d gold?\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- gtk_window_set_title(GTK_WINDOW(shell), _("Upgrade Obsolete Units"));
- if (dialogs_on_top) {
- gtk_window_set_transient_for(GTK_WINDOW(shell),
- GTK_WINDOW(toplevel));
- }
- gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_YES);
-
- if (gtk_dialog_run(GTK_DIALOG(shell)) == GTK_RESPONSE_YES) {
- request_unit_upgrade(punit);
- }
- gtk_widget_destroy(shell);
- } else {
- shell = gtk_message_dialog_new(NULL,
- 0,
- GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
- _("Upgrading %s to %s costs %d gold.\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
+ if (!punit) {
+ return;
+ }
+
+ if (get_unit_upgrade_info(buf, sizeof(buf), punit) == UR_OK) {
+ shell = gtk_message_dialog_new(NULL, 0,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, buf);
+ gtk_window_set_title(GTK_WINDOW(shell), _("Upgrade Unit!"));
+ if (dialogs_on_top) {
+ gtk_window_set_transient_for(GTK_WINDOW(shell),
+ GTK_WINDOW(toplevel));
+ }
+ g_signal_connect(shell, "response", G_CALLBACK(gtk_widget_destroy),
+ NULL);
+ gtk_window_present(GTK_WINDOW(shell));
+ } else {
+ shell = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ buf);
+ gtk_window_set_title(GTK_WINDOW(shell), _("Upgrade Obsolete Units"));
+ if (dialogs_on_top) {
+ gtk_window_set_transient_for(GTK_WINDOW(shell),
+ GTK_WINDOW(toplevel));
+ }
+ gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_YES);
- gtk_window_set_title(GTK_WINDOW(shell), _("Upgrade Unit!"));
- if (dialogs_on_top) {
- gtk_window_set_transient_for(GTK_WINDOW(shell),
- GTK_WINDOW(toplevel));
- }
- g_signal_connect(shell, "response", G_CALLBACK(gtk_widget_destroy),
- NULL);
- gtk_window_present(GTK_WINDOW(shell));
- }
+ if (gtk_dialog_run(GTK_DIALOG(shell)) == GTK_RESPONSE_YES) {
+ request_unit_upgrade(punit);
}
+ gtk_widget_destroy(shell);
}
}
Index: client/gui-win32/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/citydlg.c,v
retrieving revision 1.66
diff -u -r1.66 citydlg.c
--- client/gui-win32/citydlg.c 2003/12/08 06:34:37 1.66
+++ client/gui-win32/citydlg.c 2003/12/22 02:02:08
@@ -1523,52 +1523,29 @@
*****************************************************************/
static void upgrade_callback(HWND w, void * data)
{
- struct unit *punit;
+ struct unit *punit = player_find_unit_by_id(game.player_ptr,
+ (size_t) data);
char buf[512];
- int ut1,ut2;
- int value;
-
- if((punit=player_find_unit_by_id(game.player_ptr, (size_t)data))) {
- ut1=punit->type;
- /* printf("upgrade_callback for %s\n", unit_types[ut1].name); */
-
- ut2=can_upgrade_unittype(game.player_ptr,ut1);
-
- if (ut2==-1) {
- /* this shouldn't generally happen, but it is conceivable */
- my_snprintf(buf, sizeof(buf),
- _("Sorry: cannot upgrade %s."), unit_types[ut1].name);
- popup_message_dialog(NULL, /*"upgradenodialog"*/_("Upgrade Unit!"), buf,
- _("Darn"), unitupgrade_callback_no, 0,
- NULL);
- } else {
- value=unit_upgrade_price(game.player_ptr, ut1, ut2);
-
- if(game.player_ptr->economic.gold>=value) {
- my_snprintf(buf, sizeof(buf), _("Upgrade %s to %s for %d gold?\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- popup_message_dialog(NULL,
- /*"upgradedialog"*/_("Upgrade Obsolete Units"),
buf,
- _("_Yes"),
- unitupgrade_callback_yes, (void *)(punit->id),
- _("_No"),
- unitupgrade_callback_no, 0,
- NULL);
- } else {
- my_snprintf(buf, sizeof(buf), _("Upgrading %s to %s costs %d gold.\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- popup_message_dialog(NULL,
- /*"upgradenodialog"*/_("Upgrade Unit!"), buf,
- _("Darn"), unitupgrade_callback_no, 0,
- NULL);
- }
- }
- destroy_message_dialog(w);
+
+ if (!punit) {
+ return;
}
+
+ if (get_unit_upgrade_info(buf, sizeof(buf), punit) == UR_OK) {
+ popup_message_dialog(NULL,
+ _("Upgrade Obsolete Units"), buf,
+ _("_Yes"),
+ unitupgrade_callback_yes, (void *)(punit->id),
+ _("_No"),
+ unitupgrade_callback_no, 0,
+ NULL);
+ } else {
+ popup_message_dialog(NULL, _("Upgrade Unit!"), buf,
+ _("Darn"), unitupgrade_callback_no, 0,
+ NULL);
+ }
+
+ destroy_message_dialog(w);
}
/**************************************************************************
Index: client/gui-xaw/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/citydlg.c,v
retrieving revision 1.107
diff -u -r1.107 citydlg.c
--- client/gui-xaw/citydlg.c 2003/11/28 17:37:20 1.107
+++ client/gui-xaw/citydlg.c 2003/12/22 02:02:08
@@ -2020,50 +2020,26 @@
*****************************************************************/
void upgrade_callback(Widget w, XtPointer client_data, XtPointer call_data)
{
- struct unit *punit;
+ struct unit *punit = player_find_unit_by_id(game.player_ptr,
+ (size_t)client_data);
char buf[512];
- int ut1,ut2;
- int value;
- if((punit=player_find_unit_by_id(game.player_ptr, (size_t)client_data))) {
- ut1 = punit->type;
- /* printf("upgrade_callback for %s\n", unit_types[ut1].name); */
-
- ut2 = can_upgrade_unittype(game.player_ptr,ut1);
-
- if ( ut2 == -1 ) {
- /* this shouldn't generally happen, but it is conceivable */
- my_snprintf(buf, sizeof(buf),
- _("Sorry: cannot upgrade %s."), unit_types[ut1].name);
- popup_message_dialog(toplevel, "upgradenodialog", buf,
- unitupgrade_callback_no, 0, 0,
- NULL);
- } else {
- value=unit_upgrade_price(game.player_ptr, ut1, ut2);
+ if (!punit) {
+ return;
+ }
- if(game.player_ptr->economic.gold>=value) {
- my_snprintf(buf, sizeof(buf),
- _("Upgrade %s to %s for %d gold?\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- popup_message_dialog(toplevel, "upgradedialog", buf,
- unitupgrade_callback_yes,
- INT_TO_XTPOINTER(punit->id), 0,
- unitupgrade_callback_no, 0, 0, NULL);
- } else {
- my_snprintf(buf, sizeof(buf),
- _("Upgrading %s to %s costs %d gold.\n"
- "Treasury contains %d gold."),
- unit_types[ut1].name, unit_types[ut2].name,
- value, game.player_ptr->economic.gold);
- popup_message_dialog(toplevel, "upgradenodialog", buf,
- unitupgrade_callback_no, 0, 0,
- NULL);
- }
- }
- destroy_message_dialog(w);
+ if (get_unit_upgrade_info(buf, sizeof(buf), punit) == UR_OK) {
+ popup_message_dialog(toplevel, "upgradedialog", buf,
+ unitupgrade_callback_yes,
+ INT_TO_XTPOINTER(punit->id), 0,
+ unitupgrade_callback_no, 0, 0, NULL);
+ } else {
+ popup_message_dialog(toplevel, "upgradenodialog", buf,
+ unitupgrade_callback_no, 0, 0,
+ NULL);
}
+
+ destroy_message_dialog(w);
}
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.190
diff -u -r1.190 unit.c
--- common/unit.c 2003/11/28 17:37:21 1.190
+++ common/unit.c 2003/12/22 02:02:09
@@ -1513,3 +1513,118 @@
punit->pgr = NULL;
}
}
+
+/****************************************************************************
+ Expensive function to check how many units are in the transport.
+****************************************************************************/
+int get_transporter_occupancy(struct unit *ptrans)
+{
+ int occupied = 0;
+
+ unit_list_iterate(map_get_tile(ptrans->x, ptrans->y)->units, pcargo) {
+ if (pcargo->transported_by == ptrans->id) {
+ occupied++;
+ }
+ } unit_list_iterate_end;
+
+ return occupied;
+}
+
+/***************************************************************************
+ Tests if the unit could be updated. Returns UR_OK if is this is
+ possible.
+
+ need_money: Leonardo upgrade for free, in all other cases the unit
+ owner has to pay
+ need_city: Leonardo upgrade everywhere, all other cases the unit has
+ to be inside an owned city
+
+ Note that this function is strongly tied to unittools.c:upgrade_unit().
+***************************************************************************/
+enum unit_upgrade_result test_unit_upgrade(struct unit *punit, bool is_free)
+{
+ struct player *pplayer = unit_owner(punit);
+ Unit_Type_id to_unittype = can_upgrade_unittype(pplayer, punit->type);
+ struct city *pcity;
+ int cost;
+
+ if (to_unittype == -1) {
+ return UR_NO_UNITTYPE;
+ }
+
+ cost = unit_upgrade_price(pplayer, punit->type, to_unittype);
+ if (!is_free && pplayer->economic.gold < cost) {
+ return UR_NO_MONEY;
+ }
+
+ pcity = map_get_city(punit->x, punit->y);
+ if (!is_free && !pcity) {
+ return UR_NOT_IN_CITY;
+ }
+ if (!is_free && city_owner(pcity) != pplayer) {
+ /* TODO: should upgrades in allied cities be possible? */
+ return UR_NOT_CITY_OWNER;
+ }
+
+ if (get_transporter_occupancy(punit) >
+ unit_types[to_unittype].transport_capacity) {
+ /* TODO: allow transported units to be reassigned. Check for
+ * ground_unit_transporter_capacity here and make changes to
+ * upgrade_unit. */
+ return UR_NOT_ENOUGH_ROOM;
+ }
+
+ return UR_OK;
+}
+
+/**************************************************************************
+ Find the result of trying to upgrade the unit, and a message that
+ most callers can use directly.
+**************************************************************************/
+enum unit_upgrade_result get_unit_upgrade_info(char *buf, size_t bufsz,
+ struct unit *punit)
+{
+ enum unit_upgrade_result result = test_unit_upgrade(punit, FALSE);
+ int upgrade_cost;
+ Unit_Type_id from_unittype = punit->type;
+ Unit_Type_id to_unittype = can_upgrade_unittype(punit->type,
+ game.player_ptr);
+
+ switch (result) {
+ case UR_OK:
+ upgrade_cost = unit_upgrade_price(game.player_ptr,
+ from_unittype, to_unittype);
+ /* This message is targeted toward the GUI callers. */
+ my_snprintf(buf, bufsz, _("Upgrade %s to %s for %d gold?\n"
+ "Treasury contains %d gold."),
+ unit_types[from_unittype].name, unit_types[to_unittype].name,
+ upgrade_cost, game.player_ptr->economic.gold);
+ break;
+ case UR_NO_UNITTYPE:
+ my_snprintf(buf, bufsz,
+ _("Sorry, cannot upgrade %s (yet)."),
+ unit_types[from_unittype].name);
+ break;
+ case UR_NO_MONEY:
+ upgrade_cost = unit_upgrade_price(game.player_ptr,
+ from_unittype, to_unittype);
+ my_snprintf(buf, bufsz,
+ _("Upgrading %s to %s costs %d gold.\n"
+ "Treasury contains %d gold."),
+ unit_types[from_unittype].name, unit_types[to_unittype].name,
+ upgrade_cost, game.player_ptr->economic.gold);
+ break;
+ case UR_NOT_IN_CITY:
+ case UR_NOT_CITY_OWNER:
+ my_snprintf(buf, bufsz,
+ _("You can only upgrade units in your cities."));
+ break;
+ case UR_NOT_ENOUGH_ROOM:
+ my_snprintf(buf, bufsz,
+ _("Upgrading this %s would strand units it transports."),
+ unit_types[from_unittype].name);
+ break;
+ }
+
+ return result;
+}
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.105
diff -u -r1.105 unit.h
--- common/unit.h 2003/12/01 18:14:22 1.105
+++ common/unit.h 2003/12/22 02:02:09
@@ -92,6 +92,15 @@
sewer but city has no sewer */
};
+enum unit_upgrade_result {
+ UR_OK,
+ UR_NO_UNITTYPE,
+ UR_NO_MONEY,
+ UR_NOT_IN_CITY,
+ UR_NOT_CITY_OWNER,
+ UR_NOT_ENOUGH_ROOM
+};
+
struct unit_ai {
bool control; /* 0: not automated 1: automated */
enum ai_unit_task ai_role;
@@ -293,5 +302,11 @@
Unit_Type_id type, bool make_veteran);
void destroy_unit_virtual(struct unit *punit);
void free_unit_goto_route(struct unit *punit);
+
+int get_transporter_occupancy(struct unit *ptrans);
+
+enum unit_upgrade_result test_unit_upgrade(struct unit *punit, bool is_free);
+enum unit_upgrade_result get_unit_upgrade_info(char *buf, size_t bufsz,
+ struct unit *punit);
#endif /* FC__UNIT_H */
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.280
diff -u -r1.280 unithand.c
--- server/unithand.c 2003/12/15 19:14:50 1.280
+++ server/unithand.c 2003/12/22 02:02:10
@@ -153,83 +153,71 @@
const Unit_Type_id from_unittype = type;
const Unit_Type_id to_unittype = can_upgrade_unittype(pplayer,
from_unittype);
+ int number_of_upgraded_units = 0;
if (to_unittype == -1) {
notify_player(pplayer,
_("Game: Illegal packet, can't upgrade %s (yet)."),
- unit_types[from_unittype].name);
- } else {
- const int cost = unit_upgrade_price(pplayer, from_unittype, to_unittype);
- int number_of_upgraded_units = 0;
-
- if (pplayer->economic.gold >= cost) {
- const int player_no = pplayer->player_no;
+ unit_types[from_unittype].name);
+ return;
+ }
- /* Try to upgrade units. The order we upgrade in is arbitrary (if
- * the player really cared they should have done it manually). */
- conn_list_do_buffer(&pplayer->connections);
- unit_list_iterate(pplayer->units, punit) {
- if (punit->type == from_unittype) {
- const struct city * const pcity = map_get_city(punit->x, punit->y);
-
- /* Only units in cities can be upgraded. */
- if (pcity && pcity->owner == player_no) {
- upgrade_unit(punit, to_unittype);
- number_of_upgraded_units++;
- if ((pplayer->economic.gold -= cost) < cost) {
- /* We can't upgrade any more units. */
- break;
- }
- }
- }
- } unit_list_iterate_end;
- conn_list_do_unbuffer(&pplayer->connections);
+ /*
+ * Try to upgrade units. The order we upgrade in is arbitrary (if
+ * the player really cared they should have done it manually).
+ */
+ conn_list_do_buffer(&pplayer->connections);
+ unit_list_iterate(pplayer->units, punit) {
+ if (punit->type == from_unittype) {
+ enum unit_upgrade_result result = test_unit_upgrade(punit, FALSE);
+
+ if (result == UR_OK) {
+ number_of_upgraded_units++;
+ upgrade_unit(punit, to_unittype, FALSE);
+ } else if (result == UR_NO_MONEY) {
+ break;
+ }
}
+ } unit_list_iterate_end;
+ conn_list_do_unbuffer(&pplayer->connections);
- /* Alert the player about what happened. */
- if (number_of_upgraded_units > 0) {
- notify_player(pplayer, _("Game: %d %s upgraded to %s for %d gold."),
- number_of_upgraded_units, unit_types[from_unittype].name,
- unit_types[to_unittype].name,
- cost * number_of_upgraded_units);
- send_player_info(pplayer, pplayer);
- } else {
- notify_player(pplayer, _("Game: No units could be upgraded."));
- }
+ /* Alert the player about what happened. */
+ if (number_of_upgraded_units > 0) {
+ const int cost = unit_upgrade_price(pplayer, from_unittype, to_unittype);
+ notify_player(pplayer, _("Game: %d %s upgraded to %s for %d gold."),
+ number_of_upgraded_units, unit_types[from_unittype].name,
+ unit_types[to_unittype].name,
+ cost * number_of_upgraded_units);
+ send_player_info(pplayer, pplayer);
+ } else {
+ notify_player(pplayer, _("Game: No units could be upgraded."));
}
}
/**************************************************************************
Upgrade a single unit.
- TODO: should upgrades in allied cities be possible?
**************************************************************************/
void handle_unit_upgrade(struct player *pplayer, int unit_id)
{
- int cost;
- int from_unit, to_unit;
struct unit *punit = player_find_unit_by_id(pplayer, unit_id);
+ char buf[512];
- if (!punit || !map_get_city(punit->x, punit->y)) {
+ if (!punit) {
return;
}
- from_unit = punit->type;
- if((to_unit=can_upgrade_unittype(pplayer, punit->type)) == -1) {
- notify_player(pplayer, _("Game: Illegal package, can't upgrade %s
(yet)."),
- unit_type(punit)->name);
- return;
- }
- cost = unit_upgrade_price(pplayer, punit->type, to_unit);
- if(cost > pplayer->economic.gold) {
- notify_player(pplayer, _("Game: Insufficient funds, upgrade costs %d."),
- cost);
- return;
+ if (get_unit_upgrade_info(buf, sizeof(buf), punit) == UR_OK) {
+ Unit_Type_id from_unit = punit->type;
+ Unit_Type_id to_unit = can_upgrade_unittype(pplayer, punit->type);
+ int cost = unit_upgrade_price(pplayer, punit->type, to_unit);
+
+ upgrade_unit(punit, to_unit, FALSE);
+ send_player_info(pplayer, pplayer);
+ notify_player(pplayer, _("Game: %s upgraded to %s for %d gold."),
+ unit_name(from_unit), unit_name(to_unit), cost);
+ } else {
+ notify_player(pplayer, _("Game: %s"), buf);
}
- pplayer->economic.gold -= cost;
- upgrade_unit(punit, to_unit);
- send_player_info(pplayer, pplayer);
- notify_player(pplayer, _("Game: %s upgraded to %s for %d gold."),
- unit_name(from_unit), unit_name(to_unit), cost);
}
/***************************************************************
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.267
diff -u -r1.267 unittools.c
--- server/unittools.c 2003/12/04 18:32:45 1.267
+++ server/unittools.c 2003/12/22 02:02:11
@@ -59,7 +59,6 @@
static void unit_restore_movepoints(struct player *pplayer, struct unit
*punit);
static void update_unit_activity(struct unit *punit);
static void wakeup_neighbor_sentries(struct unit *punit);
-static bool upgrade_would_strand(struct unit *punit, int upgrade_type);
static void handle_leonardo(struct player *pplayer);
static void sentry_transported_idle_units(struct unit *ptrans);
@@ -158,63 +157,11 @@
}
/***************************************************************************
- Return 1 if upgrading this unit could cause passengers to
- get stranded at sea, due to transport capacity changes
- caused by the upgrade.
- Return 0 if ok to upgrade (as far as stranding goes).
-***************************************************************************/
-static bool upgrade_would_strand(struct unit *punit, int upgrade_type)
-{
- int old_cap, new_cap, tile_cap, tile_ncargo;
-
- if (!is_sailing_unit(punit))
- return FALSE;
- if (!is_ocean(map_get_terrain(punit->x, punit->y))) {
- return FALSE;
- }
-
- /* With weird non-standard unit types, upgrading these could
- cause air units to run out of fuel; too bad. */
- if (unit_flag(punit, F_CARRIER)
- || unit_flag(punit, F_MISSILE_CARRIER))
- return FALSE;
-
- old_cap = get_transporter_capacity(punit);
- new_cap = unit_types[upgrade_type].transport_capacity;
-
- if (new_cap >= old_cap)
- return FALSE;
-
- tile_cap = 0;
- tile_ncargo = 0;
- unit_list_iterate(map_get_tile(punit->x, punit->y)->units, punit2) {
- if (punit2->owner == punit->owner
- || pplayers_allied(unit_owner(punit2), unit_owner(punit))) {
- if (is_sailing_unit(punit2) && is_ground_units_transport(punit2)) {
- tile_cap += get_transporter_capacity(punit2);
- } else if (is_ground_unit(punit2)) {
- tile_ncargo++;
- }
- }
- }
- unit_list_iterate_end;
-
- if (tile_ncargo <= tile_cap - old_cap + new_cap)
- return FALSE;
-
- freelog(LOG_VERBOSE, "Can't upgrade %s at (%d,%d)"
- " because would strand passenger(s)",
- unit_type(punit)->name, punit->x, punit->y);
- return TRUE;
-}
-
-/***************************************************************************
Do Leonardo's Workshop upgrade(s). Select unit to upgrade by random. --Zamar
Now be careful not to strand units at sea with the Workshop. --dwp
****************************************************************************/
static void handle_leonardo(struct player *pplayer)
{
- int upgrade_type;
int leonardo_variant;
struct unit_list candidates;
@@ -227,9 +174,9 @@
unit_list_init(&candidates);
unit_list_iterate(pplayer->units, punit) {
- if ((upgrade_type=can_upgrade_unittype(pplayer, punit->type))!=-1 &&
- !upgrade_would_strand(punit, upgrade_type))
- unit_list_insert(&candidates, punit); /* Potential candidate :) */
+ if (test_unit_upgrade(punit, TRUE) == UR_OK) {
+ unit_list_insert(&candidates, punit); /* Potential candidate :) */
+ }
} unit_list_iterate_end;
if (unit_list_size(&candidates) == 0)
@@ -241,7 +188,8 @@
i=0;
unit_list_iterate(candidates, punit) {
if (leonardo_variant != 0 || i == candidate_to_upgrade) {
- upgrade_type=can_upgrade_unittype(pplayer, punit->type);
+ Unit_Type_id upgrade_type = can_upgrade_unittype(pplayer, punit->type);
+
notify_player(pplayer,
_("Game: %s has upgraded %s to %s%s."),
improvement_types[B_LEONARDO].name,
@@ -249,7 +197,8 @@
get_unit_type(upgrade_type)->name,
get_location_str_in(pplayer, punit->x, punit->y));
punit->veteran = FALSE;
- upgrade_unit(punit, upgrade_type);
+ assert(test_unit_upgrade(punit, TRUE) == UR_OK);
+ upgrade_unit(punit, upgrade_type, FALSE);
}
i++;
} unit_list_iterate_end;
@@ -1418,30 +1367,29 @@
}
}
-/****************************************************************************
- Expensive function to check how many units are in the transport.
-****************************************************************************/
-int get_transporter_occupancy(struct unit *ptrans)
-{
- int occupied = 0;
+/**************************************************************************
+ Really upgrades a single unit.
- unit_list_iterate(map_get_tile(ptrans->x, ptrans->y)->units, pcargo) {
- if (pcargo->transported_by == ptrans->id) {
- occupied++;
- }
- } unit_list_iterate_end;
+ Before calling this function you should use unit_upgrade to test if
+ this is possible.
- return occupied;
-}
+ has_to_pay: Leonardo upgrade for free, in all other cases the unit
+ owner has to pay
-/**************************************************************************
-...
+ Note that this function is strongly tied to unit.c:test_unit_upgrade().
**************************************************************************/
-void upgrade_unit(struct unit *punit, Unit_Type_id to_unit)
+void upgrade_unit(struct unit *punit, Unit_Type_id to_unit, bool is_free)
{
struct player *pplayer = unit_owner(punit);
int range;
int old_mr = unit_move_rate(punit), old_hp = unit_type(punit)->hp;
+
+ assert(test_unit_upgrade(punit, is_free) == UR_OK);
+
+ if (!is_free) {
+ pplayer->economic.gold -=
+ unit_upgrade_price(pplayer, punit->type, to_unit);
+ }
/* save old vision range */
if (map_has_special(punit->x, punit->y, S_FORTRESS)
Index: server/unittools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v
retrieving revision 1.58
diff -u -r1.58 unittools.h
--- server/unittools.h 2003/11/28 17:37:22 1.58
+++ server/unittools.h 2003/12/22 02:02:11
@@ -29,7 +29,6 @@
/* move check related */
bool is_airunit_refuel_point(int x, int y, struct player *pplayer,
Unit_Type_id type, bool unit_is_on_tile);
-int get_transporter_occupancy(struct unit *ptrans);
/* turn update related */
void player_restore_units(struct player *pplayer);
@@ -51,7 +50,7 @@
void bounce_unit(struct unit *punit, bool verbose);
/* creation/deletion/upgrading */
-void upgrade_unit(struct unit *punit, Unit_Type_id to_unit);
+void upgrade_unit(struct unit *punit, Unit_Type_id to_unit, bool has_to_pay);
struct unit *create_unit(struct player *pplayer, int x, int y, Unit_Type_id
type,
bool make_veteran, int homecity_id, int moves_left);
struct unit *create_unit_full(struct player *pplayer, int x, int y,
|
|