<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40407 >
Hi Melanie, Thanks - but this wasn't my patch (I didn't code it). Nicolas did. Richard -----Original Message----- From: Madeline Book [mailto:[EMAIL PROTECTED] Sent: Tuesday, 12 August 2008 6:30 AM To: [EMAIL PROTECTED] Subject: (PR#40407) Wishlist for Freeciv <URL: http://bugs.freeciv.org/Ticket/Display.html?id=40407 > > [nicorwadh - Sun Aug 10 21:28:18 2008]: > > Attached patch is one way of how this feature > could be implemented in current trunk version. I > created two new options in the game for this: > one on the server side called "seecitydefender", > which is disabled by default. Once enabled the > server will send the info about the strongest > unit occupying any city within vision so it can > be displayed. > > For the displaying on the client there is the > second option "draw_units_in_cities" that I > incorporated so far only in the gtk-2.0 GUI. This > is the reason why I enabled it by default, so > players using other GUI's that have no way yet > to change this view option will have no drawback > when playing on a server with seecitydefender > enabled. If this option is disabled on the > server side you should still be able to see full > unit stacks on top of own and allied cities with > the client side option enabled. I tried your patch, but it sometimes did not show the best defender (as in the one with the highest defence power). I used the editor to make a city, put a bunch of different units inside and moved them in and out of the city over a few turns). :? Style-wise, don't use camel case (e.g. defValue, refValue) when all the code around it uses underscores to seperate words in variable/function names. The biggest problem I have is the efficiency of can_player_see_city_defender. It should not be necessary to iterate the entire list of units in the city each time the result of this function is needed. I think a better design would be to have a field in the city struct that designates which unit is to be shown as the "best defender" (perhaps even just a unit type, unless the criteria for "best defender" also takes into account unit hitpoints). This field is set by the server whenever the units in the city change, and sent to the client in a city info packet if the client is allowed to known that information (server setting is set and client can see inside that city). Otherwise the client is sent an "empty" value for that field (e.g. -1 or whatever convention works). The client draws the "best defender" according to the information in the city field and if its own view option is set (it might be good to have a shortcut for this too). Generally, I agree with Per that "best defender" is a relative term so the client could be misled under certain circumstances, so I'm not really convinced of the benefit of having this feature. :| ----------------------------------------------------------------------- 聖戦じゃなくて、殺戮だと思った。
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40407 > > [EMAIL PROTECTED] - Sa 26. Jul 2008, 23:03:29]: > Hmmm, I can't remember if you can see the strongest unit inside ANY city > (sorry). I guess from a tactical/logical point of view it doesn't make > sense that you can see what the 'enemy' has in its defences. > > However I think it's definitely required for your own cities - OK, I'll make > a wish-list request. I dunno how it was in civ2 but in civ3 you could only see the strongest enemy unit defending a city on top of the sprite of the city, while you could always see your full stacks of units. Attached patch is one way of how this feature could be implemented in current trunk version. I created two new options in the game for this: one on the server side called "seecitydefender", which is disabled by default. Once enabled the server will send the info about the strongest unit occupying any city within vision so it can be displayed. For the displaying on the client there is the second option "draw_units_in_cities" that I incorporated so far only in the gtk-2.0 GUI. This is the reason why I enabled it by default, so players using other GUI's that have no way yet to change this view option will have no drawback when playing on a server with seecitydefender enabled. If this option is disabled on the server side you should still be able to see full unit stacks on top of own and allied cities with the client side option enabled. Greetings, NicoTitle: Re: [Freeciv-Dev] (PR#40407) Wishlist for Freeciv
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40407 >
> [EMAIL PROTECTED] - Sa 26. Jul 2008, 23:03:29]:
> Hmmm, I can't remember if you can see the strongest unit inside ANY city
> (sorry). I guess from a tactical/logical point of view it doesn't make
> sense that you can see what the 'enemy' has in its defences.
>
> However I think it's definitely required for your own cities - OK, I'll make
> a wish-list request.
I dunno how it was in civ2 but in civ3 you could only see the strongest enemy
unit defending a city on top of the sprite of the city, while you could
always see your full stacks of units.
Attached patch is one way of how this feature could be implemented in current
trunk version. I created two new options in the game for this: one on the
server side called "seecitydefender", which is disabled by default. Once
enabled the server will send the info about the strongest unit occupying any
city within vision so it can be displayed.
For the displaying on the client there is the second
option "draw_units_in_cities" that I incorporated so far only in the gtk-2.0
GUI. This is the reason why I enabled it by default, so players using other
GUI's that have no way yet to change this view option will have no drawback
when playing on a server with seecitydefender enabled.
If this option is disabled on the server side you should still be able to see
full unit stacks on top of own and allied cities with the client side option
enabled.
Greetings,
Nico
diff -Nur -X.diff_ignore trunk/client/control.c changed/client/control.c --- trunk/client/control.c 2008-07-27 21:46:43.000000000 +0200 +++ changed/client/control.c 2008-08-10 22:03:55.000000000 +0200 @@ -602,7 +602,7 @@ } /* If a city is here, return nothing (unit hidden by city). */ - if (tile_city(ptile)) { + if (tile_city(ptile) && !draw_units_in_cities) { return NULL; } @@ -1833,6 +1833,19 @@ } /************************************************************************** + Toggle option to display units on top of cities +**************************************************************************/ +void request_toggle_units_in_cities(void) +{ + if (!can_client_change_view()) { + return; + } + + draw_units_in_cities ^= 1; + update_map_canvas_visible(); +} + +/************************************************************************** ... **************************************************************************/ void request_center_focus_unit(void) @@ -2849,6 +2862,14 @@ } /************************************************************************** +... +**************************************************************************/ +void key_units_in_cities_toggle(void) +{ + request_toggle_units_in_cities(); +} + +/************************************************************************** Toggle editor mode in the server. **************************************************************************/ void key_editor_toggle(void) diff -Nur -X.diff_ignore trunk/client/control.h changed/client/control.h --- trunk/client/control.h 2008-07-27 21:46:43.000000000 +0200 +++ changed/client/control.h 2008-08-10 21:59:47.000000000 +0200 @@ -110,6 +110,7 @@ void request_toggle_units(void); void request_toggle_focus_unit(void); void request_toggle_fog_of_war(void); +void request_toggle_units_in_cities(void); void wakeup_sentried_units(struct tile *ptile); @@ -154,6 +155,7 @@ void key_units_toggle(void); void key_focus_unit_toggle(void); void key_fog_of_war_toggle(void); +void key_units_in_cities_toggle(void); void key_end_turn(void); void key_city_outlines_toggle(void); void key_city_output_toggle(void); diff -Nur -X.diff_ignore trunk/client/gui-gtk-2.0/menu.c changed/client/gui-gtk-2.0/menu.c --- trunk/client/gui-gtk-2.0/menu.c 2008-08-02 22:46:09.000000000 +0200 +++ changed/client/gui-gtk-2.0/menu.c 2008-08-10 22:12:48.000000000 +0200 @@ -118,6 +118,7 @@ MENU_VIEW_SHOW_UNITS, MENU_VIEW_SHOW_FOCUS_UNIT, MENU_VIEW_SHOW_FOG_OF_WAR, + MENU_VIEW_SHOW_UNITS_IN_CITIES, MENU_VIEW_FULL_SCREEN, MENU_VIEW_CENTER_VIEW, @@ -397,6 +398,10 @@ if (draw_fog_of_war ^ GTK_CHECK_MENU_ITEM(widget)->active) key_fog_of_war_toggle(); break; + case MENU_VIEW_SHOW_UNITS_IN_CITIES: + if (draw_units_in_cities ^ GTK_CHECK_MENU_ITEM(widget)->active) + key_units_in_cities_toggle(); + break; case MENU_VIEW_FULL_SCREEN: if (fullscreen_mode ^ GTK_CHECK_MENU_ITEM(widget)->active) { fullscreen_mode ^= 1; @@ -862,7 +867,9 @@ { "/" N_("View") "/" N_("Units"), NULL, view_menu_callback, MENU_VIEW_SHOW_UNITS, "<CheckItem>" }, { "/" N_("View") "/" N_("Focus Unit"), NULL, - view_menu_callback, MENU_VIEW_SHOW_FOCUS_UNIT, "<CheckItem>" }, + view_menu_callback, MENU_VIEW_SHOW_FOCUS_UNIT, "<CheckItem>" }, + { "/" N_("View") "/" N_("Units in Cities"), NULL, + view_menu_callback, MENU_VIEW_SHOW_UNITS_IN_CITIES, "<CheckItem>" }, { "/" N_("View") "/" N_("Fog of War"), NULL, view_menu_callback, MENU_VIEW_SHOW_FOG_OF_WAR, "<CheckItem>" }, { "/" N_("View") "/sep2", NULL, @@ -1463,6 +1470,8 @@ menus_set_active("<main>/_View/Focus Unit", draw_focus_unit); menus_set_sensitive("<main>/_View/Focus Unit", !draw_units); menus_set_active("<main>/_View/Fog of War", draw_fog_of_war); + menus_set_active("<main>/_View/Units in Cities", draw_units_in_cities); + menus_set_sensitive("<main>/_View/Units in Cities", draw_units); menus_set_active("<main>/_View/_Full Screen", fullscreen_mode); diff -Nur -X.diff_ignore trunk/client/options.c changed/client/options.c --- trunk/client/options.c 2008-08-02 22:46:10.000000000 +0200 +++ changed/client/options.c 2008-08-10 22:17:14.000000000 +0200 @@ -310,6 +310,7 @@ bool draw_pollution = TRUE; bool draw_cities = TRUE; bool draw_units = TRUE; +bool draw_units_in_cities = TRUE; bool draw_focus_unit = FALSE; bool draw_fog_of_war = TRUE; bool draw_borders = TRUE; @@ -338,6 +339,7 @@ VIEW_OPTION(draw_specials), VIEW_OPTION(draw_pollution), VIEW_OPTION(draw_cities), + VIEW_OPTION(draw_units_in_cities), VIEW_OPTION(draw_units), VIEW_OPTION(draw_focus_unit), VIEW_OPTION(draw_fog_of_war), diff -Nur -X.diff_ignore trunk/client/options.h changed/client/options.h --- trunk/client/options.h 2008-08-02 22:46:10.000000000 +0200 +++ changed/client/options.h 2008-08-10 22:13:29.000000000 +0200 @@ -160,6 +160,7 @@ extern bool draw_units; extern bool draw_focus_unit; extern bool draw_fog_of_war; +extern bool draw_units_in_cities; extern bool draw_borders; extern bool draw_full_citybar; extern bool draw_unit_shields; diff -Nur -X.diff_ignore trunk/common/game.c changed/common/game.c --- trunk/common/game.c 2008-08-02 22:45:57.000000000 +0200 +++ changed/common/game.c 2008-08-10 22:43:54.000000000 +0200 @@ -287,6 +287,7 @@ game.info.spacerace = GAME_DEFAULT_SPACERACE; game.info.turnblock = GAME_DEFAULT_TURNBLOCK; game.info.fogofwar = GAME_DEFAULT_FOGOFWAR; + game.info.seecitydefender = GAME_DEFAULT_SEECITYDEFENDER; game.info.borders_sq = GAME_DEFAULT_BORDERS; game.info.happyborders = GAME_DEFAULT_HAPPYBORDERS; game.info.slow_invasions= GAME_DEFAULT_SLOW_INVASIONS; diff -Nur -X.diff_ignore trunk/common/game.h changed/common/game.h --- trunk/common/game.h 2008-08-02 22:45:57.000000000 +0200 +++ changed/common/game.h 2008-08-10 22:42:49.000000000 +0200 @@ -193,6 +193,8 @@ #define GAME_DEFAULT_FOGOFWAR TRUE +#define GAME_DEFAULT_SEECITYDEFENDER FALSE + /* 0 means no national borders. */ #define GAME_DEFAULT_BORDERS (4*4+1*1) #define GAME_MIN_BORDERS 0 diff -Nur -X.diff_ignore trunk/common/packets.def changed/common/packets.def --- trunk/common/packets.def 2008-08-02 22:45:57.000000000 +0200 +++ changed/common/packets.def 2008-08-10 22:44:39.000000000 +0200 @@ -416,7 +416,8 @@ BOOL turnblock; BOOL fixedlength; BOOL auto_ai_toggle; - BOOL fogofwar; + BOOL fogofwar; + BOOL seecitydefender; UINT8 borders_sq; BOOL happyborders; BOOL slow_invasions; diff -Nur -X.diff_ignore trunk/server/citytools.c changed/server/citytools.c --- trunk/server/citytools.c 2008-08-02 22:46:03.000000000 +0200 +++ changed/server/citytools.c 2008-08-10 22:33:52.000000000 +0200 @@ -1437,11 +1437,13 @@ /* After city has been transferred, some players may no longer see inside. */ players_iterate(pplayer) { if (BV_ISSET(saw_entering, player_index(pplayer)) - && !can_player_see_unit_at(pplayer, punit, pcity->tile)) { + && !can_player_see_unit_at(pplayer, punit, pcity->tile) + && !can_player_see_city_defender(pplayer, punit)) { /* Player saw unit entering, but now unit is hiding inside city */ unit_goes_out_of_sight(pplayer, punit); } else if (!BV_ISSET(saw_entering, player_index(pplayer)) - && can_player_see_unit_at(pplayer, punit, pcity->tile)) { + && (can_player_see_unit_at(pplayer, punit, pcity->tile) + || can_player_see_city_defender(pplayer, punit))) { /* Player sees inside cities of new owner */ send_unit_info_to_onlookers(pplayer->connections, punit, pcity->tile, FALSE); diff -Nur -X.diff_ignore trunk/server/savegame.c changed/server/savegame.c --- trunk/server/savegame.c 2008-08-02 22:46:03.000000000 +0200 +++ changed/server/savegame.c 2008-08-10 22:50:28.000000000 +0200 @@ -3978,6 +3978,7 @@ game.info.fogofwar = secfile_lookup_bool_default(file, FALSE, "game.fogofwar"); game.fogofwar_old = game.info.fogofwar; + game.info.seecitydefender = secfile_lookup_bool_default(file, FALSE, "game.seecitydefender"); game.info.civilwarsize = secfile_lookup_int_default(file, GAME_DEFAULT_CIVILWARSIZE, @@ -4620,6 +4621,8 @@ secfile_insert_str(file, server.game_identifier, "game.id"); secfile_insert_bool(file, game.info.fogofwar, "game.fogofwar"); + secfile_insert_bool(file, game.info.seecitydefender, + "game.seecitydefender"); secfile_insert_bool(file, game.info.spacerace, "game.spacerace"); secfile_insert_bool(file, game.info.auto_ai_toggle, "game.auto_ai_toggle"); secfile_insert_int(file, game.info.diplchance, "game.diplchance"); diff -Nur -X.diff_ignore trunk/server/settings.c changed/server/settings.c --- trunk/server/settings.c 2008-08-02 22:46:03.000000000 +0200 +++ changed/server/settings.c 2008-08-10 22:47:02.000000000 +0200 @@ -776,6 +776,14 @@ "changes in tiles not observed."), NULL, GAME_DEFAULT_FOGOFWAR) + GEN_BOOL("seecitydefender", game.info.seecitydefender, + SSET_RULES, SSET_MILITARY, SSET_RARE, SSET_TO_CLIENT, + N_("Strongest unit defending enemy city visible"), + N_("If this is set to 1 you you can see the strongest unit of " + "other players defending a city. Other units occupying " + "the given city will remain hidden, though."), NULL, + GAME_DEFAULT_SEECITYDEFENDER) + GEN_INT("diplchance", game.info.diplchance, SSET_RULES_FLEXIBLE, SSET_MILITARY, SSET_SITUATIONAL, SSET_TO_CLIENT, N_("Base chance for diplomats and spies to succeed."), diff -Nur -X.diff_ignore trunk/server/unithand.c changed/server/unithand.c --- trunk/server/unithand.c 2008-07-27 21:44:04.000000000 +0200 +++ changed/server/unithand.c 2008-08-10 22:29:25.000000000 +0200 @@ -787,10 +787,12 @@ * Remove the client knowledge of the units. This corresponds to the * send_packet_unit_short_info calls up above. */ - if (!can_player_see_unit(other_player, pattacker)) { + if (!can_player_see_unit(other_player, pattacker) + && !can_player_see_city_defender(other_player, pattacker)) { unit_goes_out_of_sight(other_player, pattacker); } - if (!can_player_see_unit(other_player, pdefender)) { + if (!can_player_see_unit(other_player, pdefender) + && !can_player_see_city_defender(other_player, pdefender)) { unit_goes_out_of_sight(other_player, pdefender); } } diff -Nur -X.diff_ignore trunk/server/unittools.c changed/server/unittools.c --- trunk/server/unittools.c 2008-07-27 21:44:04.000000000 +0200 +++ changed/server/unittools.c 2008-08-10 22:40:15.000000000 +0200 @@ -1586,6 +1586,14 @@ } } unit_list_iterate_safe_end; } + + /* With seecitydefender enabled we need to to send an update wich other + * unit is defending this city now the previous one has been wiped out */ + if (tile_city(ptile) && game.info.seecitydefender) { + unit_list_iterate_safe(ptile->units, potherUnits) { + send_unit_info(NULL, potherUnits); + } unit_list_iterate_safe_end; + } } /************************************************************************** @@ -1929,13 +1937,15 @@ send_packet_unit_info(pconn, &info); } else if (pplayer) { bool see_in_old; - bool see_in_new = can_player_see_unit_at(pplayer, punit, punit->tile); + bool see_in_new = can_player_see_unit_at(pplayer, punit, punit->tile) + || can_player_see_city_defender(pplayer, punit); if (punit->tile == ptile) { /* This is not about movement */ see_in_old = see_in_new; } else { - see_in_old = can_player_see_unit_at(pplayer, punit, ptile); + see_in_old = can_player_see_unit_at(pplayer, punit, ptile) + || can_player_see_city_defender(pplayer, punit); } if (see_in_new || see_in_old) { @@ -1982,7 +1992,8 @@ players_iterate(unitowner) { unit_list_iterate(unitowner->units, punit) { - if (!pplayer || can_player_see_unit(pplayer, punit)) { + if (!pplayer || can_player_see_unit(pplayer, punit) + || can_player_see_city_defender(pplayer, punit)) { send_unit_info_to_onlookers(pconn->self, punit, punit->tile, FALSE); } @@ -2370,6 +2381,44 @@ } } +/**************************************************************************** + Check if enemy unit should be seen defending a city. If the owner + of the unit is not pplayer this will return TRUE only for the + single best defending unit of the stack so others should remain hidden +****************************************************************************/ +bool can_player_see_city_defender(struct player *pplayer, struct unit *punit) +{ + if (pplayer == unit_owner(punit)) { + return TRUE; + } + if (game.info.seecitydefender && tile_city(punit->tile)) { + if (unit_list_size(punit->tile->units) > 1) { + int defValue = get_defense_power(punit); + bool same = FALSE; + bool first = FALSE; + unit_list_iterate(punit->tile->units, prefunit) { + if (prefunit == punit) { + /* If there are units with the same defensive power present + * we just select the first one appearing on the units list */ + first = !same; + continue; + } + int refValue = get_defense_power(prefunit); + if (refValue > defValue) { + /* better defender present, abort */ + return FALSE; + } else if (refValue == defValue) { + same = TRUE; + } + } unit_list_iterate_end; + return first; + } else { + return TRUE; + } + } + return FALSE; +} + /***************************************************************** Check if unit survives enemy autoattacks. We assume that any unit that is adjacent to us can see us. diff -Nur -X.diff_ignore trunk/server/unittools.h changed/server/unittools.h --- trunk/server/unittools.h 2008-07-27 21:44:04.000000000 +0200 +++ changed/server/unittools.h 2008-08-10 23:09:01.000000000 +0200 @@ -52,6 +52,8 @@ void unit_list_refresh_vision(struct unit_list *punitlist); void pay_for_units(struct player *pplayer, struct city *pcity); void bounce_unit(struct unit *punit, bool verbose); +bool can_player_see_city_defender(struct player *pplayer, + struct unit *punit); /* creation/deletion/upgrading */ void upgrade_unit(struct unit *punit, struct unit_type *to_unit,
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev