diff -Nur -Xdiff_ignore freeciv_cvs/ai/aicity.c freeciv/ai/aicity.c --- freeciv_cvs/ai/aicity.c Tue Jan 23 14:45:02 2001 +++ freeciv/ai/aicity.c Thu Feb 8 14:20:47 2001 @@ -395,10 +395,8 @@ unit_types[bestchoice.choice].name); notify_player(pplayer, _("Game: %s disbanded in %s."), unit_types[punit->type].name, pcity->name); - /* FIXME: should be handled in server... */ - pcity->shield_stock+=(get_unit_type(punit->type)->build_cost/2); - send_city_info(pplayer, pcity); - wipe_unit_safe(punit, &myiter); + + do_unit_disband_safe(pcity, punit, &myiter); } } } diff -Nur -Xdiff_ignore freeciv_cvs/client/packhand.c freeciv/client/packhand.c --- freeciv_cvs/client/packhand.c Fri Jan 26 14:37:08 2001 +++ freeciv/client/packhand.c Thu Feb 8 14:20:47 2001 @@ -351,6 +351,8 @@ pcity->changed_from_id=packet->changed_from_id; pcity->changed_from_is_unit=packet->changed_from_is_unit; pcity->before_change_shields=packet->before_change_shields; + pcity->unit_disbanded_shields=packet->unit_disbanded_shields; + pcity->caravan_shields=packet->caravan_shields; i=0; for(y=0; yshield_stock; + int shield_stock_after_adjustment; + enum building_class_type orig_class; + enum building_class_type new_class; + int put_penalty; /* boolean */ - freelog(LOG_DEBUG, "compute change-production penalty: %s -> %s", - pcity->is_building_unit ? - unit_types[pcity->currently_building].name : - improvement_types[pcity->currently_building].name, - is_unit ? - unit_types[target].name : - improvement_types[target].name - ); - freelog(LOG_DEBUG, - "before: (stock=%d last/test=%d/%d changed=%d year=%d orig: %d %s)", - pcity->shield_stock, - pcity->turn_last_built, game_next_year(pcity->turn_last_built), - pcity->turn_changed_target, game.year, - pcity->before_change_shields, - pcity->changed_from_is_unit ? - unit_types[pcity->changed_from_id].name : - improvement_types[pcity->changed_from_id].name - ); + if (pcity->changed_from_is_unit) + orig_class=TYPE_UNIT; + else if (is_wonder(pcity->changed_from_id)) + orig_class=TYPE_WONDER; + else + orig_class=TYPE_NORMAL_IMPROVEMENT; - /* If already building this thing, nothing to do... */ - if ((pcity->is_building_unit == is_unit) && - (pcity->currently_building == target)) { - freelog(LOG_DEBUG, "...did not change production; do nothing"); - return shield_stock_after_adjustment; - } + if (is_unit) + new_class=TYPE_UNIT; + else if (is_wonder(target)) + new_class=TYPE_WONDER; + else + new_class=TYPE_NORMAL_IMPROVEMENT; - /* We're changing production... */ - if (((pcity->is_building_unit != is_unit) || - (!is_unit && - (is_wonder(pcity->currently_building) != is_wonder(target)))) && - (game_next_year(pcity->turn_last_built) < game.year)) { - /* We've changed "class", and it's not the turn immed after completion. */ - freelog(LOG_DEBUG, "...changed prod class in latter year"); - if (pcity->turn_changed_target != game.year) { - /* This is the first change this turn... */ - freelog(LOG_DEBUG, " ...first change this year; penalty"); - /* Compute new shield_stock after production penalty. */ - shield_stock_after_adjustment /= 2; - /* Only if really applying the penalty... */ - if (apply_it) { - /* Apply the penalty. */ - pcity->shield_stock = shield_stock_after_adjustment; - /* Only set turn_changed_target when we actually cop the penalty - - otherwise you can change to something of the same class first, - and suffer no penalty for any later changes in the same turn. */ - pcity->turn_changed_target = game.year; - } - } else if ((pcity->changed_from_is_unit == is_unit) && - (is_unit || - (is_wonder(pcity->changed_from_id) == is_wonder(target)))) { - /* This is a change back to the initial production class... */ - freelog(LOG_DEBUG, " ...revert to initial production class"); - /* Compute new shield_stock after reverting penalty. */ - shield_stock_after_adjustment = pcity->before_change_shields; - /* Only if really applying the penalty... */ - if (apply_it) { - /* Undo penalty. */ - pcity->shield_stock = shield_stock_after_adjustment; - /* Pretend we havn't changed this turn. */ - pcity->turn_changed_target = GAME_START_YEAR; - } -#ifdef DEBUG - } else { - freelog(LOG_DEBUG, " ...latter change in year; no penalty"); -#endif - } -#ifdef DEBUG - } else { - freelog(LOG_DEBUG, "...same class or first year; no penalty"); -#endif - } + put_penalty = (orig_class != new_class && + game_next_year(pcity->turn_last_built) < game.year)? 1 : 0; + + if (put_penalty) + shield_stock_after_adjustment = pcity->before_change_shields/2; + else + shield_stock_after_adjustment = pcity->before_change_shields; - freelog(LOG_DEBUG, - "--> %-3d (stock=%d last/test=%d/%d changed=%d year=%d orig: %d %s)", - shield_stock_after_adjustment, - pcity->shield_stock, - pcity->turn_last_built, game_next_year(pcity->turn_last_built), - pcity->turn_changed_target, game.year, - pcity->before_change_shields, - pcity->changed_from_is_unit ? - unit_types[pcity->changed_from_id].name : - improvement_types[pcity->changed_from_id].name - ); + /* Do not put penalty on these. It shouldn't matter whether you disband unit + before or after changing production...*/ + shield_stock_after_adjustment += pcity->unit_disbanded_shields; + if (new_class == TYPE_WONDER) /* No penalty! */ + shield_stock_after_adjustment += pcity->caravan_shields; + else /* Same as you had disbanded caravans. 50 percent penalty is logical! */ + shield_stock_after_adjustment += pcity->caravan_shields/2; + + if (apply_it) { + pcity->shield_stock = shield_stock_after_adjustment; + + if (new_class != orig_class) + pcity->turn_changed_target = game.year; + /* Do we really need this at all? */ + else + pcity->turn_changed_target = GAME_START_YEAR; + /* Pretend we have changed nothing */ + } + return shield_stock_after_adjustment; } diff -Nur -Xdiff_ignore freeciv_cvs/common/city.h freeciv/common/city.h --- freeciv_cvs/common/city.h Tue Jan 23 14:45:16 2001 +++ freeciv/common/city.h Thu Feb 8 14:20:47 2001 @@ -23,6 +23,9 @@ struct government; struct tile; +enum building_class_type { + TYPE_UNIT, TYPE_NORMAL_IMPROVEMENT, TYPE_WONDER +}; enum specialist_type { SP_ELVIS, SP_SCIENTIST, SP_TAXMAN @@ -215,6 +218,8 @@ int turn_changed_target; /* Suffer shield loss at most once per turn */ int changed_from_id; /* If changed this turn, what changed from (id) */ int changed_from_is_unit; /* If changed this turn, what changed from (unit?) */ + int unit_disbanded_shields; /* If you disband unit in a city. Count them */ + int caravan_shields; /* If caravan has helped city to build wonder. */ int before_change_shields; /* If changed this turn, shields before penalty */ int anarchy; /* anarchy rounds count */ int rapture; /* rapture rounds count */ diff -Nur -Xdiff_ignore freeciv_cvs/common/packets.c freeciv/common/packets.c --- freeciv_cvs/common/packets.c Thu Jan 25 14:25:57 2001 +++ freeciv/common/packets.c Thu Feb 8 14:20:47 2001 @@ -2237,6 +2237,11 @@ cptr=put_uint16(cptr, req->before_change_shields); } +if (pc && has_capability("production_change_fix2", pc->capability)) { + cptr=put_uint16(cptr, req->unit_disbanded_shields); + cptr=put_uint16(cptr, req->caravan_shields); +} + /* when removing "worklist_true_ids" capability, may want to remove the 'pc' argument (?) */ cptr=put_worklist(cptr, &req->worklist, pc, 1); @@ -2325,6 +2330,14 @@ packet->turn_changed_target = GAME_START_YEAR; packet->changed_from_id = packet->currently_building; packet->before_change_shields = packet->shield_stock; +} + +if (pc && has_capability("production_change_fix2", pc->capability)) { + iget_uint16(&iter, &packet->unit_disbanded_shields); + iget_uint16(&iter, &packet->caravan_shields); +} else { + packet->unit_disbanded_shields = 0; + packet->caravan_shields = 0; } /* when removing "worklist_true_ids" capability, diff -Nur -Xdiff_ignore freeciv_cvs/common/packets.h freeciv/common/packets.h --- freeciv_cvs/common/packets.h Thu Jan 25 14:25:57 2001 +++ freeciv/common/packets.h Thu Feb 8 14:20:47 2001 @@ -346,6 +346,8 @@ int changed_from_id; int changed_from_is_unit; int before_change_shields; + int unit_disbanded_shields; + int caravan_shields; struct worklist worklist; diff -Nur -Xdiff_ignore freeciv_cvs/server/cityhand.c freeciv/server/cityhand.c --- freeciv_cvs/server/cityhand.c Sat Jan 20 14:41:15 2001 +++ freeciv/server/cityhand.c Thu Feb 8 14:20:47 2001 @@ -197,6 +197,8 @@ pcity->changed_from_id = 0; pcity->changed_from_is_unit = 0; pcity->before_change_shields = 0; + pcity->unit_disbanded_shields = 0; + pcity->caravan_shields = 0; pcity->anarchy=0; pcity->rapture=0; @@ -505,6 +507,9 @@ pplayer->economic.gold-=cost; if (pcity->shield_stock < total){ + /* As we never put penalty on unit_disbanded_shields, we can + * fully well add the missing shields there. */ + pcity->unit_disbanded_shields += total - pcity->shield_stock; pcity->shield_stock=total; /* AI wants this -- Syela */ pcity->did_buy=1; /* !PS: no need to set buy flag otherwise */ } @@ -1032,6 +1037,8 @@ packet->changed_from_id=pcity->changed_from_id; packet->changed_from_is_unit=pcity->changed_from_is_unit; packet->before_change_shields=pcity->before_change_shields; + packet->unit_disbanded_shields=pcity->unit_disbanded_shields; + packet->caravan_shields=pcity->caravan_shields; copy_worklist(&packet->worklist, pcity->worklist); packet->diplomat_investigate=dipl_invest; diff -Nur -Xdiff_ignore freeciv_cvs/server/citytools.c freeciv/server/citytools.c --- freeciv_cvs/server/citytools.c Mon Jan 15 14:42:46 2001 +++ freeciv/server/citytools.c Thu Feb 8 14:20:47 2001 @@ -1052,7 +1052,7 @@ pcity->improvements[i]=0; } } - pcity->before_change_shields = 0; + nullify_prechange_production(pcity); pcity->shield_stock = 0; } diff -Nur -Xdiff_ignore freeciv_cvs/server/cityturn.c freeciv/server/cityturn.c --- freeciv_cvs/server/cityturn.c Sun Feb 4 14:25:28 2001 +++ freeciv/server/cityturn.c Thu Feb 8 17:42:25 2001 @@ -82,8 +82,9 @@ static void disband_city(struct city *pcity); -static void begin_city_turn(struct player *pplayer, struct city *pcity); +static void define_orig_production_values(struct city *pcity); static int update_city_activity(struct player *pplayer, struct city *pcity); +static void nullify_caravan_and_disband_plus(struct city *pcity); static void worker_loop(struct city *pcity, int *foodneed, int *prodneed, int *workers); @@ -836,7 +837,7 @@ void begin_cities_turn(struct player *pplayer) { city_list_iterate(pplayer->cities, pcity) - begin_city_turn(pplayer, pcity); + define_orig_production_values(pcity); city_list_iterate_end; } @@ -1307,11 +1308,16 @@ } unit_list_iterate_end; } - + + /* Now we confirm changes made last turn. */ pcity->shield_stock+=pcity->shield_surplus; + pcity->before_change_shields=pcity->shield_stock; + nullify_caravan_and_disband_plus(pcity); + if (!pcity->is_building_unit) { if (pcity->currently_building==B_CAPITAL) { pplayer->economic.gold+=pcity->shield_surplus; + pcity->before_change_shields=0; pcity->shield_stock=0; } upgrade_building_prod(pcity); @@ -1321,7 +1327,8 @@ pcity->name,get_impr_name_ex(pcity, pcity->currently_building)); return 1; } - if (pcity->shield_stock>=improvement_value(pcity->currently_building)) { + if (pcity->before_change_shields>= + improvement_value(pcity->currently_building)) { if (pcity->currently_building==B_PALACE) { city_list_iterate(pplayer->cities, palace) if (city_got_building(palace, B_PALACE)) { @@ -1342,7 +1349,9 @@ space_part = 0; pcity->improvements[pcity->currently_building]=1; } - pcity->shield_stock-=improvement_value(pcity->currently_building); + pcity->before_change_shields-= + improvement_value(pcity->currently_building); + pcity->shield_stock-=improvement_value(pcity->currently_building); pcity->turn_last_built = game.year; /* to eliminate micromanagement */ if(is_wonder(pcity->currently_building)) { @@ -1407,7 +1416,7 @@ /* FIXME: F_CITIES should be changed to any unit * that 'contains' 1 (or more) pop -- sjolie */ - if(pcity->shield_stock>=unit_value(pcity->currently_building)) { + if(pcity->before_change_shields>=unit_value(pcity->currently_building)) { if (unit_flag(pcity->currently_building, F_CITIES)) { if (pcity->size==1) { @@ -1433,7 +1442,8 @@ do_make_unit_veteran(pcity, pcity->currently_building), pcity->id, -1); /* to eliminate micromanagement, we only subtract the unit's cost */ - pcity->shield_stock-=unit_value(pcity->currently_building); + pcity->before_change_shields-=unit_value(pcity->currently_building); + pcity->shield_stock-=unit_value(pcity->currently_building); if (city_built_city_builder) { pcity->size--; @@ -1713,13 +1723,13 @@ /************************************************************************** Called every turn, at beginning of turn, for every city. **************************************************************************/ -static void begin_city_turn(struct player *pplayer, struct city *pcity) +static void define_orig_production_values(struct city *pcity) { /* remember what this city is building at start of turn, so user can switch production back without penalty */ pcity->changed_from_id = pcity->currently_building; pcity->changed_from_is_unit = pcity->is_building_unit; - pcity->before_change_shields = pcity->shield_stock; + freelog(LOG_DEBUG, "In %s, building %s. Beg of Turn shields = %d", pcity->name, @@ -1728,6 +1738,18 @@ improvement_types[pcity->changed_from_id].name, pcity->before_change_shields ); +} + +static void nullify_caravan_and_disband_plus(struct city *pcity) +{ + pcity->unit_disbanded_shields=0; + pcity->caravan_shields=0; +} + +void nullify_prechange_production(struct city *pcity) +{ + nullify_caravan_and_disband_plus(pcity); + pcity->before_change_shields=0; } /************************************************************************** diff -Nur -Xdiff_ignore freeciv_cvs/server/cityturn.h freeciv/server/cityturn.h --- freeciv_cvs/server/cityturn.h Sun Feb 4 14:25:28 2001 +++ freeciv/server/cityturn.h Thu Feb 8 17:42:41 2001 @@ -39,4 +39,5 @@ void remove_obsolete_buildings_city(struct city *pcity, int refresh); void remove_obsolete_buildings(struct player *plr); +void nullify_prechange_production(struct city *pcity); #endif /* FC__CITYTURN_H */ diff -Nur -Xdiff_ignore freeciv_cvs/server/diplomats.c freeciv/server/diplomats.c --- freeciv_cvs/server/diplomats.c Mon Jan 15 14:42:47 2001 +++ freeciv/server/diplomats.c Thu Feb 8 14:20:47 2001 @@ -803,7 +803,8 @@ pcity->name, get_nation_name (pplayer->nation)); pcity->shield_stock = 0; - + nullify_prechange_production(pcity); + /* You get a technology advance, too! */ get_a_tech (pplayer, cplayer); @@ -981,7 +982,8 @@ /* Do it. */ pcity->shield_stock = 0; - /* Report it. */ + nullify_prechange_production(pcity); /* Make it impossible to recover */ + /* Report it. */ if (pcity->is_building_unit) prod = unit_name (pcity->currently_building); else diff -Nur -Xdiff_ignore freeciv_cvs/server/savegame.c freeciv/server/savegame.c --- freeciv_cvs/server/savegame.c Thu Jan 4 14:39:22 2001 +++ freeciv/server/savegame.c Thu Feb 8 14:20:47 2001 @@ -776,7 +776,13 @@ pcity->before_change_shields= secfile_lookup_int_default(file, pcity->shield_stock, "player%d.c%d.before_change_shields", plrno, i); - + pcity->unit_disbanded_shields= + secfile_lookup_int_default(file, 0, + "player%d.c%d.unit_disbanded_shields", plrno, i); + pcity->caravan_shields= + secfile_lookup_int_default(file, 0, + "player%d.c%d.caravan_shields", plrno, i); + pcity->did_buy=secfile_lookup_int(file, "player%d.c%d.did_buy", plrno,i); pcity->did_sell = @@ -1418,6 +1424,11 @@ "player%d.c%d.changed_from_is_unit", plrno, i); secfile_insert_int(file, pcity->before_change_shields, "player%d.c%d.before_change_shields", plrno, i); + secfile_insert_int(file, pcity->unit_disbanded_shields, + "player%d.c%d.unit_disbanded_shields", plrno, i); + secfile_insert_int(file, pcity->caravan_shields, + "player%d.c%d.caravan_shields", plrno, i); + secfile_insert_int(file, pcity->anarchy, "player%d.c%d.anarchy", plrno,i); secfile_insert_int(file, pcity->rapture, "player%d.c%d.rapture", plrno,i); secfile_insert_int(file, pcity->was_happy, "player%d.c%d.was_happy", plrno,i); diff -Nur -Xdiff_ignore freeciv_cvs/server/unithand.c freeciv/server/unithand.c --- freeciv_cvs/server/unithand.c Wed Feb 7 14:31:19 2001 +++ freeciv/server/unithand.c Thu Feb 8 14:20:47 2001 @@ -333,7 +333,25 @@ Disband a unit. If its in a city, add 1/2 of the worth of the unit to the city's shield stock for the current production. "iter" may be NULL, see wipe_unit_safe for details. + NOTE: Ai calls do_unit_disband_safe directly, but player calls + of course handle_unit_disband_safe **************************************************************************/ +void do_unit_disband_safe(struct city *pcity, struct unit *punit, + struct genlist_iterator *iter) +{ + if (pcity) { + pcity->shield_stock+=(get_unit_type(punit->type)->build_cost/2); + /* If we change production later at this turn. No penalty is added. */ + pcity->unit_disbanded_shields+=(get_unit_type(punit->type)->build_cost/2); + + /* Note: Nowadays it's possible to disband unit in allied city and + * your ally receives those shields. Should it be like this? Why not? + * That's why we must use city_owner instead of pplayer -- Zamar */ + send_city_info(city_owner(pcity), pcity); + } + wipe_unit_safe(punit, iter); +} + void handle_unit_disband_safe(struct player *pplayer, struct packet_unit_request *req, struct genlist_iterator *iter) @@ -341,11 +359,8 @@ struct unit *punit; struct city *pcity; if((punit=player_find_unit_by_id(pplayer, req->unit_id))) { - if ((pcity=map_get_city(punit->x, punit->y))) { - pcity->shield_stock+=(get_unit_type(punit->type)->build_cost/2); - send_city_info(pplayer, pcity); - } - wipe_unit_safe(punit, iter); + pcity=map_get_city(punit->x, punit->y); + do_unit_disband_safe(pcity, punit, iter); } } @@ -1147,10 +1162,13 @@ /* we're there! */ pcity_dest->shield_stock+=50; - if (build_points_left(pcity_dest) < 0) { + pcity_dest->caravan_shields+=50; /*If we change production we dont lose them*/ + + /*if (build_points_left(pcity_dest) < 0) { pcity_dest->shield_stock = improvement_value(pcity_dest->currently_building); - } - + }*/ + /* No need for this. Overproduction should take care of this -- Zamar */ + conn_list_do_buffer(&pplayer->connections); notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, _("Game: Your %s helps build the %s in %s (%d remaining)."), diff -Nur -Xdiff_ignore freeciv_cvs/server/unithand.h freeciv/server/unithand.h --- freeciv_cvs/server/unithand.h Tue Jan 9 14:40:23 2001 +++ freeciv/server/unithand.h Thu Feb 8 14:20:47 2001 @@ -33,6 +33,8 @@ void handle_unit_disband_safe(struct player *pplayer, struct packet_unit_request *req, struct genlist_iterator *iter); +void do_unit_disband_safe(struct city *pcity, struct unit *punit, + struct genlist_iterator *iter); /* Ai uses this directly */ void handle_unit_build_city(struct player *pplayer, struct packet_unit_request *req); void handle_unit_info(struct player *pplayer, struct packet_unit_info *pinfo);