[Freeciv-Dev] Gold upkeep (v2)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
This is a revised patch which allow gold upkeep for units.
Some errors revealed by Per have been fixed.
I have updated the gtk-1.2 client. Now the economic report shows the
gold upkeeped units, the units report has a gold column and the city
dialog can display a small icon on the units which need gold. However,
the other clients still know nothing about gold upkeep.
The tiles.png attachment is a part of the isotrident tilespec. He
contains the new icons for gold upkeeps. Please be indulgent, I know
they are ugly but they are not for release and only if you want to test
them quickly. Note that now, there is two new fields needed in tilesets:
"upkeep.gold" and "upkeep.gold2"
Remi Bonnet
diff -u -r common.orig/city.c common/city.c
--- common.orig/city.c 2003-05-14 06:58:01.000000000 +0200
+++ common/city.c 2003-06-21 14:08:49.000000000 +0200
@@ -46,6 +46,7 @@
static void unhappy_city_check(struct city *pcity);
static void set_pollution(struct city *pcity);
static void set_food_trade_shields(struct city *pcity);
+static int citygov_free_gold(struct city *pcity, struct government *gov);
static void city_support(struct city *pcity,
void (*send_unit_info) (struct player * pplayer,
struct unit * punit));
@@ -906,7 +907,8 @@
}
/*************************************************************************
-Calculate amount of gold remaining in city after paying for buildings
+Calculate amount of gold remaining in city after paying for buildings and
+units
*************************************************************************/
int city_gold_surplus(struct city *pcity)
{
@@ -917,6 +919,10 @@
cost += improvement_upkeep_asmiths(pcity, i, asmiths);
} built_impr_iterate_end;
+ unit_list_iterate(pcity->units_supported, punit) {
+ cost += punit->upkeep_gold;
+ } unit_list_iterate_end;
+
return pcity->tax_total-cost;
}
diff -u -r common.orig/unittype.h common/unittype.h
--- common.orig/unittype.h 2003-02-01 06:57:19.000000000 +0100
+++ common/unittype.h 2003-06-21 14:04:50.000000000 +0200
@@ -181,7 +181,7 @@
int happy_cost; /* unhappy people in home city */
int shield_cost; /* normal upkeep cost */
int food_cost; /* settler food cost */
- int gold_cost; /* gold upkeep (n/a now, maybe later) */
+ int gold_cost; /* gold upkeep */
int paratroopers_range; /* only valid for F_PARATROOPERS */
int paratroopers_mr_req;
diff -u -r client.orig/gui-gtk/mapview.c client/gui-gtk/mapview.c
--- client.orig/gui-gtk/mapview.c 2003-05-14 06:58:00.000000000 +0200
+++ client/gui-gtk/mapview.c 2003-06-21 20:16:38.000000000 +0200
@@ -950,13 +950,15 @@
/**************************************************************************
FIXME:
- For now only two food, one shield and two masks can be drawn per unit,
- the proper way to do this is probably something like what Civ II does.
- (One food/shield/mask drawn N times, possibly one top of itself. -- SKi
+ For now only two food, two golds, one shield and two masks can be drawn
+ per unit, the proper way to do this is probably something like what Civ II
+ does. (One food/shield/mask drawn N times, possibly one top of itself.
+ -- SKi
**************************************************************************/
void put_unit_gpixmap_city_overlays(struct unit *punit, GtkPixcomm *p)
{
int upkeep_food = CLIP(0, punit->upkeep_food, 2);
+ int upkeep_gold = CLIP(0, punit->upkeep_gold, 2);
int unhappy = CLIP(0, punit->unhappiness, 2);
/* draw overlay pixmaps */
@@ -964,6 +966,10 @@
put_overlay_tile_gpixmap(p, 0, NORMAL_TILE_HEIGHT, sprites.upkeep.shield);
if (upkeep_food > 0)
put_overlay_tile_gpixmap(p, 0, NORMAL_TILE_HEIGHT,
sprites.upkeep.food[upkeep_food-1]);
+ if (upkeep_gold > 0) {
+ put_overlay_tile_gpixmap(p, 0, NORMAL_TILE_HEIGHT,
+ sprites.upkeep.gold[upkeep_gold - 1]);
+ }
if (unhappy > 0)
put_overlay_tile_gpixmap(p, 0, NORMAL_TILE_HEIGHT,
sprites.upkeep.unhappy[unhappy-1]);
}
diff -u -r client.orig/gui-gtk/repodlgs.c client/gui-gtk/repodlgs.c
--- client.orig/gui-gtk/repodlgs.c 2003-04-05 07:56:48.000000000 +0200
+++ client/gui-gtk/repodlgs.c 2003-06-21 19:30:14.000000000 +0200
@@ -33,6 +33,7 @@
#include "civclient.h"
#include "clinet.h"
#include "repodlgs_common.h"
+#include "control.h"
#include "cityrep.h"
#include "dialogs.h"
@@ -67,7 +68,12 @@
static void economy_selloff_callback(GtkWidget * w, gpointer data);
static void economy_list_callback(GtkWidget * w, gint row, gint column);
static void economy_list_ucallback(GtkWidget * w, gint row, gint column);
-static int economy_improvement_type[B_LAST];
+
+struct economy_row {
+ int is_impr;
+ int type;
+};
+static struct economy_row economy_row_type[B_LAST];
static GtkWidget *economy_dialog_shell = NULL;
static GtkWidget *economy_label2;
@@ -652,14 +658,19 @@
*****************************************************************/
void economy_list_callback(GtkWidget *w, gint row, gint column)
{
- int i = economy_improvement_type[row];
- bool is_sellable = (i >= 0 && i < game.num_impr_types && !is_wonder(i));
+ int i = economy_row_type[row].type;
+
+ if (economy_row_type[row].is_impr == TRUE) {
+ bool is_sellable = (i >= 0 && i < game.num_impr_types && !is_wonder(i));
- gtk_widget_set_sensitive(sellobsolete_command, is_sellable
- && can_client_issue_orders()
- && improvement_obsolete(game.player_ptr, i));
- gtk_widget_set_sensitive(sellall_command, is_sellable
- && can_client_issue_orders());
+ gtk_widget_set_sensitive(sellobsolete_command, is_sellable
+ && can_client_issue_orders()
+ && improvement_obsolete(game.player_ptr, i));
+ gtk_widget_set_sensitive(sellall_command, is_sellable
+ && can_client_issue_orders());
+ } else {
+ gtk_widget_set_sensitive(sellall_command, can_client_issue_orders());
+ }
}
/****************************************************************
@@ -684,38 +695,63 @@
*****************************************************************/
void economy_selloff_callback(GtkWidget *w, gpointer data)
{
- int i,count=0,gold=0;
+ int count=0, gold=0;
+ struct economy_row row_type;
struct packet_city_request packet;
char str[64];
GList *selection;
- gint row;
+ int row;
while ((selection = GTK_CLIST(economy_list)->selection)) {
row = GPOINTER_TO_INT(selection->data);
- i=economy_improvement_type[row];
+ row_type = economy_row_type[row];
+
+ if (row_type.is_impr == TRUE) {
+ city_list_iterate(game.player_ptr->cities, pcity) {
+ if(!pcity->did_sell && city_got_building(pcity, row_type.type) &&
+ (data ||
+ improvement_obsolete(game.player_ptr, row_type.type) ||
+ wonder_replacement(pcity, row_type.type) )) {
+ count++; gold+=improvement_value(row_type.type);
+ packet.city_id=pcity->id;
+ packet.build_id = row_type.type;
+ send_packet_city_request(&aconnection, &packet, PACKET_CITY_SELL);
+ }
+ } city_list_iterate_end;
+
+ if(count) {
+ my_snprintf(str, sizeof(str), _("Sold %d %s for %d gold"),
+ count, get_improvement_name(row_type.type), gold);
+ } else {
+ my_snprintf(str, sizeof(str), _("No %s could be sold"),
+ get_improvement_name(row_type.type));
+ }
+ } else {
+ city_list_iterate(game.player_ptr->cities, pcity) {
+ unit_list_iterate(pcity->units_supported, punit) {
+ /* We don't sell obsolete units when sell obsolete is clicked.
+ * Indeed, unlike improvements, obsolete units can fight like
+ * up-to-date ones */
+ if (punit->type == row_type.type && data) {
+ count++;
+ request_unit_disband(punit);
+ }
+ } unit_list_iterate_end;
+ } city_list_iterate_end;
+
+ if (count > 0) {
+ my_snprintf(str, sizeof(str), "Disbanded %d %s", count,
+ unit_name(row_type.type));
+ } else {
+ my_snprintf(str, sizeof(str), "No %s could be disbanded",
+ unit_name(row_type.type));
+ }
+ }
+
+ gtk_clist_unselect_row(GTK_CLIST(economy_list),row,0);
+ popup_notify_dialog(_("Sell-Off:"),_("Results"),str);
- city_list_iterate(game.player_ptr->cities, pcity) {
- if(!pcity->did_sell && city_got_building(pcity, i) &&
- (data ||
- improvement_obsolete(game.player_ptr,i) ||
- wonder_replacement(pcity, i) )) {
- count++; gold+=improvement_value(i);
- packet.city_id=pcity->id;
- packet.build_id=i;
- send_packet_city_request(&aconnection, &packet, PACKET_CITY_SELL);
- }
- } city_list_iterate_end;
-
- if(count) {
- my_snprintf(str, sizeof(str), _("Sold %d %s for %d gold"),
- count, get_improvement_name(i), gold);
- } else {
- my_snprintf(str, sizeof(str), _("No %s could be sold"),
- get_improvement_name(i));
- }
- gtk_clist_unselect_row(GTK_CLIST(economy_list),row,0);
- popup_notify_dialog(_("Sell-Off:"),_("Results"),str);
}
return;
}
@@ -727,7 +763,7 @@
{
if(is_report_dialogs_frozen()) return;
if(economy_dialog_shell) {
- int tax, total, i, entries_used;
+ int tax, total, i, entries_used, nbr_impr;
char buf0 [64];
char buf1 [64];
char buf2 [64];
@@ -735,6 +771,7 @@
gchar *row [4];
char economy_total[48];
struct improvement_entry entries[B_LAST];
+ struct unit_entry entries_units[U_LAST];
gtk_clist_freeze(GTK_CLIST(economy_list));
gtk_clist_clear(GTK_CLIST(economy_list));
@@ -756,7 +793,27 @@
gtk_clist_append(GTK_CLIST(economy_list), row);
- economy_improvement_type[i] = p->type;
+ economy_row_type[i].is_impr = TRUE;
+ economy_row_type[i].type = p->type;
+ }
+
+ nbr_impr = entries_used;
+ entries_used = 0;
+ get_economy_report_units_data(entries_units, &entries_used, &total);
+
+ for (i = 0; i < entries_used; i++) {
+
+ my_snprintf(buf0, sizeof(buf0), "%-20s",
+ unit_name(entries_units[i].type));
+ my_snprintf(buf1, sizeof(buf1), "%5d", entries_units[i].count);
+ my_snprintf(buf2, sizeof(buf2), "%5d", entries_units[i].cost);
+ my_snprintf(buf3, sizeof(buf3), "%6d", entries_units[i].total_cost);
+
+ gtk_clist_append(GTK_CLIST(economy_list), row);
+
+ economy_row_type[i + nbr_impr].is_impr = FALSE;
+ economy_row_type[i + nbr_impr].type = entries_units[i].type;
+
}
my_snprintf(economy_total, sizeof(economy_total),
@@ -774,7 +831,7 @@
****************************************************************/
-#define AU_COL 6
+#define AU_COL 7
/****************************************************************
...
@@ -816,7 +873,7 @@
GtkWidget *close_command, *refresh_command;
static const char *titles_[AU_COL]
= { N_("Unit Type"), N_("U"), N_("In-Prog"), N_("Active"),
- N_("Shield"), N_("Food") };
+ N_("Shield"), N_("Food"), N_("Gold") };
static gchar **titles;
int i;
GtkAccelGroup *accel=gtk_accel_group_new();
@@ -974,7 +1031,7 @@
int active_count;
int upkeep_shield;
int upkeep_food;
- /* int upkeep_gold; FIXME: add gold when gold is implemented --jjm */
+ int upkeep_gold;
int building_count;
};
if(is_report_dialogs_frozen()) return;
@@ -999,6 +1056,7 @@
if (punit->homecity) {
unitarray[punit->type].upkeep_shield += punit->upkeep;
unitarray[punit->type].upkeep_food += punit->upkeep_food;
+ unitarray[punit->type].upkeep_gold += punit->upkeep_gold;
}
}
unit_list_iterate_end;
@@ -1020,6 +1078,7 @@
my_snprintf(buf[3], sizeof(buf[3]), "%9d", unitarray[i].active_count);
my_snprintf(buf[4], sizeof(buf[4]), "%9d", unitarray[i].upkeep_shield);
my_snprintf(buf[5], sizeof(buf[5]), "%9d", unitarray[i].upkeep_food);
+ my_snprintf(buf[6], sizeof(buf[6]), "%9d", unitarray[i].upkeep_gold);
gtk_clist_append( GTK_CLIST( activeunits_list ), row );
@@ -1028,17 +1087,19 @@
unittotals.active_count += unitarray[i].active_count;
unittotals.upkeep_shield += unitarray[i].upkeep_shield;
unittotals.upkeep_food += unitarray[i].upkeep_food;
+ unittotals.upkeep_gold += unitarray[i].upkeep_gold;
unittotals.building_count += unitarray[i].building_count;
}
} unit_type_iterate_end;
/* horrible kluge, but I can't get gtk_label_set_justify() to work --jjm */
my_snprintf(activeunits_total, sizeof(activeunits_total),
- _("Totals: %s%9d%s%9d%s%9d%s%9d"),
+ _("Totals: %s%9d%s%9d%s%9d%s%9d%s%9d"),
" ", unittotals.building_count,
" ", unittotals.active_count,
" ", unittotals.upkeep_shield,
- " ", unittotals.upkeep_food);
+ " ", unittotals.upkeep_food,
+ " ", unittotals.upkeep_gold);
gtk_set_label(activeunits_label2, activeunits_total);
gtk_widget_show_all(activeunits_list);
diff -u -r client.orig/repodlgs_common.c client/repodlgs_common.c
--- client.orig/repodlgs_common.c 2003-04-05 07:56:48.000000000 +0200
+++ client/repodlgs_common.c 2003-06-21 18:24:02.000000000 +0200
@@ -74,6 +74,54 @@
} city_list_iterate_end;
}
+/******************************************************************
+ Returns an array of units with gold_upkeep. Number of units in the
+ array is added to num_entries_used.
+******************************************************************/
+void get_economy_report_units_data(struct unit_entry *entries,
+ int *num_entries_used, int *total_cost)
+{
+ int count, cost, partial_cost;
+ struct unit_type *unittype;
+
+ unit_type_iterate(utype) {
+
+ unittype = get_unit_type(utype);
+ cost = utype_gold_cost(unittype, get_gov_pplayer(game.player_ptr));
+
+ if (cost == 0) {
+ continue;
+ }
+
+ count = 0;
+ partial_cost = 0;
+
+ city_list_iterate(game.player_ptr->cities, pcity) {
+ unit_list_iterate(pcity->units_supported, punit) {
+
+ if (punit->type == utype) {
+ count++;
+ partial_cost += punit->upkeep_gold;
+ }
+
+ } unit_list_iterate_end;
+ } city_list_iterate_end;
+
+ if (count == 0) {
+ continue;
+ }
+
+ (*total_cost) += partial_cost;
+
+ entries[*num_entries_used].type = utype;
+ entries[*num_entries_used].count = count;
+ entries[*num_entries_used].cost = cost;
+ entries[*num_entries_used].total_cost = partial_cost;
+ (*num_entries_used)++;
+
+ } unit_type_iterate_end;
+}
+
static int frozen_level = 0;
/******************************************************************
diff -u -r client.orig/repodlgs_common.h client/repodlgs_common.h
--- client.orig/repodlgs_common.h 2002-06-27 08:32:50.000000000 +0200
+++ client/repodlgs_common.h 2003-06-21 17:25:33.000000000 +0200
@@ -15,6 +15,7 @@
#define FC__REPODLGS_COMMON_H
#include "improvement.h"
+#include "unittype.h"
struct improvement_entry
{
@@ -22,9 +23,23 @@
int count, cost, total_cost;
};
+struct unit_entry
+{
+ Unit_Type_id type;
+ int count, cost, total_cost;
+};
+
void get_economy_report_data(struct improvement_entry *entries,
int *num_entries_used, int *total_cost,
int *total_income);
+/* This function returns an array with the gold upkeeped units.
+ * FIXME: Many clients doesn't yet use this function and show also only the
+ * buildings in the economy reports
+ * I think that there should be only one function which returns an array of
+ * char* arrays like some other common functions but that means updating all
+ * client simultaneously and I simply can't */
+void get_economy_report_units_data(struct unit_entry *entries,
+ int *num_entries_used, int *total_cost);
void report_dialogs_freeze(void);
void report_dialogs_thaw(void);
diff -u -r client.orig/tilespec.c client/tilespec.c
--- client.orig/tilespec.c 2003-04-23 06:57:44.000000000 +0200
+++ client/tilespec.c 2003-06-21 19:36:36.000000000 +0200
@@ -920,6 +920,8 @@
SET_SPRITE(upkeep.food[1], "upkeep.food2");
SET_SPRITE(upkeep.unhappy[0], "upkeep.unhappy");
SET_SPRITE(upkeep.unhappy[1], "upkeep.unhappy2");
+ SET_SPRITE(upkeep.gold[0], "upkeep.gold");
+ SET_SPRITE(upkeep.gold[1], "upkeep.gold2");
SET_SPRITE(upkeep.shield, "upkeep.shield");
SET_SPRITE(user.attention, "user.attention");
diff -u -r client.orig/tilespec.h client/tilespec.h
--- client.orig/tilespec.h 2003-04-10 06:57:18.000000000 +0200
+++ client/tilespec.h 2003-06-21 19:32:58.000000000 +0200
@@ -158,6 +158,7 @@
struct Sprite
*food[2],
*unhappy[2],
+ *gold[2],
*shield;
} upkeep;
struct {
diff -u -r server.orig/cityturn.c server/cityturn.c
--- server.orig/cityturn.c 2003-06-01 06:57:59.000000000 +0200
+++ server/cityturn.c 2003-06-21 13:55:07.000000000 +0200
@@ -413,7 +413,9 @@
update_city_activity(pplayer, pcity);
city_list_iterate_end;
pplayer->ai.prev_gold = gold;
- if (gold-(gold-pplayer->economic.gold)*3<0) {
+ /* This test include the cost of the units because pay_for_units is called
+ * in update_city_activity */
+ if (gold-(gold-pplayer->economic.gold)*3<0) {
notify_player_ex(pplayer, -1, -1, E_LOW_ON_FUNDS,
_("Game: WARNING, we're LOW on FUNDS sire."));
}
@@ -1326,6 +1328,7 @@
pcity->airlift=FALSE;
update_tech(pplayer, pcity->science_total);
pplayer->economic.gold+=pcity->tax_total;
+ pay_for_units(pplayer, pcity);
pay_for_buildings(pplayer, pcity);
if(city_unhappy(pcity)) {
diff -u -r server.orig/unittools.c server/unittools.c
--- server.orig/unittools.c 2003-06-17 06:59:16.000000000 +0200
+++ server/unittools.c 2003-06-21 14:13:37.000000000 +0200
@@ -284,6 +284,38 @@
}
/***************************************************************************
+ Pay the cost of supported units of one city
+***************************************************************************/
+void pay_for_units(struct player *pplayer, struct city *pcity)
+{
+ int potential_gold = 0;
+
+ built_impr_iterate(pcity, pimpr) {
+ potential_gold += get_improvement_type(pimpr)->build_cost;
+ } built_impr_iterate_end;
+
+ unit_list_iterate(pcity->units_supported, punit) {
+
+ if (pplayer->economic.gold + potential_gold < punit->upkeep_gold) {
+ /* We cannot upkeep this unit any longer and selling off city
+ * improvements will not help so we will have to disband */
+ assert(pplayer->economic.gold + potential_gold >= 0);
+
+ notify_player_ex(pplayer, -1, -1, E_UNIT_LOST,
+ _("Not enough gold. %s disbanded"),
+ unit_type(punit)->name);
+ wipe_unit_safe(punit, &myiter);
+ }
+ else {
+ /* Gold can get negative here as city improvements will be sold
+ * afterwards to balance our budget. Or should units with gold upkeep
+ * give gold when they are disbanded ? */
+ pplayer->economic.gold -= punit->upkeep_gold;
+ }
+ } unit_list_iterate_end;
+}
+
+/***************************************************************************
...
****************************************************************************/
static struct unit *find_best_air_unit_to_refuel(struct player *pplayer,
diff -u -r server.orig/unittools.h server/unittools.h
--- server.orig/unittools.h 2003-06-05 06:58:14.000000000 +0200
+++ server/unittools.h 2003-06-21 13:55:08.000000000 +0200
@@ -47,7 +47,7 @@
void disband_stack_conflict_unit(struct unit *punit, bool verbose);
int get_watchtower_vision(struct unit *punit);
bool unit_profits_of_watchtower(struct unit *punit);
-
+void pay_for_units(struct player *pplayer, struct city *pcity);
/* creation/deletion/upgrading */
void upgrade_unit(struct unit *punit, Unit_Type_id to_unit);
diff -u data/default/governments.ruleset data/default/governments.ruleset
--- data/default/governments.ruleset.orig 2003-06-21 20:54:40.000000000
+0200
+++ data/default/governments.ruleset 2003-06-21 20:55:40.000000000 +0200
@@ -19,6 +19,8 @@
when_anarchy="Anarchy"
ai_goal="Republic"
+
+
ai_tech_hints = { "tech", "turns_factor", "const_factor", "get_first", "done"
"Code of Laws", 150, 0, 1, 0
"The Republic", 90, 90, 0, 1
@@ -137,7 +139,7 @@
unit_free_unhappy = 0
unit_free_shield = "City_Size"
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = "City_Size"
corruption_level = 100
corruption_modifier = 40
@@ -215,7 +217,7 @@
unit_free_unhappy = 0
unit_free_shield = "City_Size"
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = "City_Size"
corruption_level = 100
corruption_modifier = 27
@@ -294,7 +296,7 @@
unit_free_unhappy = 0
unit_free_shield = 3
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = 3
corruption_level = 100
corruption_modifier = 67
@@ -372,7 +374,7 @@
unit_free_unhappy = 0
unit_free_shield = 3
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = 3
corruption_level = 50
corruption_modifier = 80
@@ -458,7 +460,7 @@
unit_free_unhappy = 1
unit_free_shield = 0
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = 2
corruption_level = 100
corruption_modifier = 67
@@ -547,7 +549,7 @@
unit_free_unhappy = 0
unit_free_shield = 0
unit_free_food = 0
-unit_free_gold = 0
+unit_free_gold = 1
corruption_level = 0
corruption_modifier = 1
diff -u data/isotrident/tiles.spec data/isotrident/tiles.spec
--- data/isotrident/tiles.spec.orig 2003-06-21 20:54:10.000000000 +0200
+++ data/isotrident/tiles.spec 2003-06-21 20:21:28.000000000 +0200
@@ -123,6 +123,8 @@
7, 16, "upkeep.food2"
7, 17, "upkeep.unhappy"
7, 18, "upkeep.unhappy2"
+ 8, 17, "upkeep.gold"
+ 8, 18, "upkeep.gold2"
7, 19, "upkeep.shield"
; Nuclear explosion: this could maybe now be handled as one
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] Gold upkeep (v2),
Remi <=
|
|