Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2005:
[Freeciv-Dev] (PR#13776) Deleting a player does not make their nation av
Home

[Freeciv-Dev] (PR#13776) Deleting a player does not make their nation av

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: dmstewart@xxxxxxxxx
Subject: [Freeciv-Dev] (PR#13776) Deleting a player does not make their nation available
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 26 Aug 2005 14:38:18 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13776 >

Here is a kindof complicated patch that should fix it (untested).

-jason

Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.179
diff -p -u -r1.179 climisc.c
--- client/climisc.c    18 Aug 2005 06:44:27 -0000      1.179
+++ client/climisc.c    26 Aug 2005 21:37:32 -0000
@@ -63,6 +63,7 @@ void client_remove_player(int plrno)
   game_remove_player(get_player(plrno));
   game_renumber_players(plrno);
   update_conn_list_dialog();
+  races_toggles_set_sensitive();
 }
 
 /**************************************************************************
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.543
diff -p -u -r1.543 packhand.c
--- client/packhand.c   25 Aug 2005 20:36:12 -0000      1.543
+++ client/packhand.c   26 Aug 2005 21:37:33 -0000
@@ -1419,11 +1419,12 @@ void handle_player_info(struct packet_pl
   char msg[MAX_LEN_MSG];
   struct player *pplayer = &game.players[pinfo->playerno];
   struct player_research* research;
+  bool is_new_nation;
 
   sz_strlcpy(pplayer->name, pinfo->name);
 
   pplayer->is_observer = pinfo->is_observer;
-  pplayer->nation = get_nation_by_idx(pinfo->nation);
+  is_new_nation = player_set_nation(pplayer, get_nation_by_idx(pinfo->nation));
   pplayer->is_male=pinfo->is_male;
   team_add_player(pplayer, team_get_by_id(pinfo->team));
   pplayer->score.game = pinfo->score;
@@ -1557,6 +1558,9 @@ void handle_player_info(struct packet_pl
 
   sz_strlcpy(pplayer->username, pinfo->username);
 
+  if (is_new_nation) {
+    races_toggles_set_sensitive();
+  }
   if (can_client_change_view()) {
     /* Just about any changes above require an update to the intelligence
      * dialog. */
@@ -2004,30 +2008,6 @@ void handle_player_remove(int player_id)
 }
 
 /**************************************************************************
-  Mark a nation as available or unavailable, in pregame.
-**************************************************************************/
-void handle_nation_available(Nation_type_id nation_no,
-                            bool is_unavailable, bool is_used)
-{
-  if (get_client_state() == CLIENT_PRE_GAME_STATE
-      && nation_no >= 0 && nation_no < game.control.nation_count) {
-    struct nation_type *nation = get_nation_by_idx(nation_no);
-    const bool changed = (nation->is_unavailable != is_unavailable
-                         || nation->is_used != is_used);
-
-    nation->is_unavailable = is_unavailable;
-    nation->is_used = is_used;
-
-    if (changed) {
-      races_toggles_set_sensitive();
-    }
-  } else {
-    freelog(LOG_ERROR,
-           "got a select nation packet in an incompatible state");
-  }
-}
-
-/**************************************************************************
   Take arrival of ruleset control packet to indicate that
   current allocated governments should be free'd, and new
   memory allocated for new size. The same for nations.
@@ -2398,6 +2378,8 @@ void handle_ruleset_nation(struct packet
     pl->groups[i] = add_new_nation_group(p->group_name[i]);
   }
 
+  pl->is_available = p->is_available;
+
   tileset_setup_nation_flag(tileset, p->id);
 }
 
Index: client/gui-gtk-2.0/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/dialogs.c,v
retrieving revision 1.116
diff -p -u -r1.116 dialogs.c
--- client/gui-gtk-2.0/dialogs.c        19 Aug 2005 07:40:16 -0000      1.116
+++ client/gui-gtk-2.0/dialogs.c        26 Aug 2005 21:37:34 -0000
@@ -1598,7 +1598,7 @@ static GtkWidget* create_list_of_nations
     GtkTreeIter it;
     GValue value = { 0, };
 
-    if (!is_nation_playable(pnation) || pnation->is_unavailable) {
+    if (!is_nation_playable(pnation) || !pnation->is_available) {
       continue;
     }
 
@@ -1610,7 +1610,7 @@ static GtkWidget* create_list_of_nations
 
     s = crop_blankspace(get_nation_flag_sprite(tileset, pnation));
     img = sprite_get_pixbuf(s);
-    used = pnation->is_used;
+    used = (pnation->player != NULL);
     gtk_list_store_set(store, &it, 0, pnation->index, 1, used, 2, img, -1);
     free_sprite(s);
 
@@ -1976,7 +1976,7 @@ void races_toggles_set_sensitive(void)
         gtk_tree_model_get(model, &it, 0, &nation_no, -1);
        nation = get_nation_by_idx(nation_no);
 
-        chosen = nation->is_unavailable || nation->is_used;
+        chosen = !nation->is_available || nation->player;
 
         gtk_list_store_set(GTK_LIST_STORE(model), &it, 1, chosen, -1);
 
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.236
diff -p -u -r1.236 game.c
--- common/game.c       18 Aug 2005 06:44:27 -0000      1.236
+++ common/game.c       26 Aug 2005 21:37:34 -0000
@@ -435,6 +435,7 @@ void game_advance_year(void)
 ****************************************************************************/
 void game_remove_player(struct player *pplayer)
 {
+  player_set_nation(pplayer, NULL);
   if (pplayer->attribute_block.data) {
     free(pplayer->attribute_block.data);
     pplayer->attribute_block.data = NULL;
@@ -488,6 +489,9 @@ void game_renumber_players(int plrno)
     conn_list_iterate(game.players[i].connections, pconn) {
       pconn->player = &game.players[i];
     } conn_list_iterate_end;
+    if (game.players[i].nation) {
+      game.players[i].nation->player = &game.players[i];
+    }
 
     /* We could renumber players in-game if we updated the unit and
      * city owners.  But for now we just make sure these lists are empty. */
Index: common/nation.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/nation.h,v
retrieving revision 1.55
diff -p -u -r1.55 nation.h
--- common/nation.h     18 Aug 2005 06:44:28 -0000      1.55
+++ common/nation.h     26 Aug 2005 21:37:34 -0000
@@ -99,9 +99,10 @@ struct nation_type {
   int num_groups;
   struct nation_group **groups;
 
-  /* Unavailable nations aren't allowed in the scenario.  Used nations are
-   * those in use by another player. */
-  bool is_unavailable, is_used;
+  /* Unavailable nations aren't allowed in the scenario. */
+  bool is_available;
+
+  struct player *player; /* Who's using the nation, or NULL. */
 };
 
 struct nation_type *find_nation_by_name(const char *name);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.153
diff -p -u -r1.153 packets.def
--- common/packets.def  20 Aug 2005 19:53:40 -0000      1.153
+++ common/packets.def  26 Aug 2005 21:37:35 -0000
@@ -293,13 +293,6 @@ end
 PACKET_SERVER_SHUTDOWN=8;sc,lsend
 end
 
-PACKET_NATION_AVAILABLE=9;sc,lsend
-  NATION id; key
-
-  BOOL is_unavailable;
-  BOOL is_used;
-end
-
 PACKET_NATION_SELECT_REQ=10;cs,dsend
   PLAYER player_no;
   NATION nation_no;
@@ -1165,7 +1158,7 @@ PACKET_RULESET_TERRAIN_CONTROL=101;sc,ls
   UINT8 fallout_tile_penalty[O_MAX]; /* % taken from output if polluted */
 end
 
-PACKET_RULESET_NATION=102;sc,lsend
+PACKET_RULESET_NATION=102;sc,lsend,is-info
   NATION id; key
 
   STRING name[MAX_LEN_NAME];
@@ -1184,7 +1177,7 @@ PACKET_RULESET_NATION=102;sc,lsend
   STRING leader_name[MAX_NUM_LEADERS:leader_count][MAX_LEN_NAME];
   BOOL leader_sex[MAX_NUM_LEADERS:leader_count];
 
-  BOOL is_playable, is_observer, is_barbarian;
+  BOOL is_available, is_playable, is_observer, is_barbarian;
   
   UINT8 group_count;
   STRING group_name[MAX_NUM_NATION_GROUPS:group_count][MAX_LEN_NAME];
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.191
diff -p -u -r1.191 player.c
--- common/player.c     22 Aug 2005 21:15:48 -0000      1.191
+++ common/player.c     26 Aug 2005 21:37:35 -0000
@@ -164,6 +164,25 @@ void player_init(struct player *plr)
   BV_CLR_ALL(plr->debug);
 }
 
+/****************************************************************************
+  Set the player's nation to the given nation (may be NULL).  Returns TRUE
+  iff there was a change.
+****************************************************************************/
+bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
+{
+  if (pplayer->nation != pnation) {
+    if (pplayer->nation) {
+      pplayer->nation->player = NULL;
+    }
+    if (pnation) {
+      pnation->player = pplayer;
+    }
+    pplayer->nation = pnation;
+    return TRUE;
+  }
+  return FALSE;
+}
+
 /***************************************************************
 ...
 ***************************************************************/
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.163
diff -p -u -r1.163 player.h
--- common/player.h     18 Aug 2005 06:44:28 -0000      1.163
+++ common/player.h     26 Aug 2005 21:37:35 -0000
@@ -204,6 +204,7 @@ struct player *find_player_by_name(const
 struct player *find_player_by_name_prefix(const char *name,
                                          enum m_pre_result *result);
 struct player *find_player_by_user(const char *name);
+bool player_set_nation(struct player *pplayer, struct nation_type *pnation);
 void player_set_unit_focus_status(struct player *pplayer);
 bool player_has_embassy(const struct player *pplayer,
                        const struct player *pplayer2);
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.100
diff -p -u -r1.100 barbarian.c
--- server/barbarian.c  22 Aug 2005 20:46:00 -0000      1.100
+++ server/barbarian.c  26 Aug 2005 21:37:35 -0000
@@ -86,7 +86,7 @@ static bool is_sea_barbarian(struct play
 struct nation_type *pick_barbarian_nation(void)
 {
   nations_iterate(pnation) {
-    if (is_nation_barbarian(pnation) && !pnation->is_used) {
+    if (is_nation_barbarian(pnation) && !pnation->player) {
       return pnation;
     }
   } nations_iterate_end;
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.344
diff -p -u -r1.344 citytools.c
--- server/citytools.c  26 Aug 2005 19:40:26 -0000      1.344
+++ server/citytools.c  26 Aug 2005 21:37:36 -0000
@@ -1210,7 +1210,8 @@ void handle_unit_enter_city(struct unit 
     /* Do a civil war only if there's an available unused nation. */
     nations_iterate(pnation) {
       if (is_nation_playable(pnation)
-         && !pnation->is_unavailable && !pnation->is_used) {
+         && pnation->is_available
+         && !pnation->player) {
        do_civil_war = TRUE;
        break;
       }
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.416
diff -p -u -r1.416 plrhand.c
--- server/plrhand.c    26 Aug 2005 19:40:26 -0000      1.416
+++ server/plrhand.c    26 Aug 2005 21:37:36 -0000
@@ -1320,7 +1320,8 @@ struct nation_type *pick_available_natio
    * 2: preferred choice */
   nations_iterate(pnation) {
     if (!is_nation_playable(pnation)
-       || pnation->is_used || pnation->is_unavailable) {
+       || pnation->player
+       || !pnation->is_available) {
       /* Nation is unplayable or already used: don't consider it. */
       nations_used[pnation->index] = UNAVAILABLE;
       match[pnation->index] = 0;
@@ -1379,7 +1380,7 @@ struct nation_type *pick_available_natio
 static struct nation_type *pick_observer_nation(void)
 {
   nations_iterate(pnation) {
-    if (is_nation_observer(pnation) && !pnation->is_used) {
+    if (is_nation_observer(pnation) && !pnation->player) {
       return pnation;
     }
   } nations_iterate_end;
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.280
diff -p -u -r1.280 ruleset.c
--- server/ruleset.c    18 Aug 2005 06:53:31 -0000      1.280
+++ server/ruleset.c    26 Aug 2005 21:37:37 -0000
@@ -101,8 +101,6 @@ static void send_ruleset_units(struct co
 static void send_ruleset_buildings(struct conn_list *dest);
 static void send_ruleset_terrain(struct conn_list *dest);
 static void send_ruleset_governments(struct conn_list *dest);
-static void send_ruleset_nations(struct conn_list *dest);
-static void send_ruleset_nations_availability(struct conn_list *dest);
 static void send_ruleset_cities(struct conn_list *dest);
 static void send_ruleset_game(struct conn_list *dest);
 
@@ -2245,8 +2243,8 @@ static void load_ruleset_nations(struct 
       pl->legend[MAX_LEN_MSG - 1] = '\0';
     }
 
-    pl->is_unavailable = FALSE;
-    pl->is_used = FALSE;
+    pl->is_available = TRUE;
+    pl->player = NULL;
   }
 
   /* Calculate parent nations.  O(n^2) algorithm. */
@@ -2935,7 +2933,7 @@ static void send_ruleset_governments(str
   Send the nations ruleset information (info on each nation) to the
   specified connections.
 **************************************************************************/
-static void send_ruleset_nations(struct conn_list *dest)
+void send_ruleset_nations(struct conn_list *dest)
 {
   struct packet_ruleset_nation packet;
   struct nation_type *n;
@@ -2980,22 +2978,6 @@ static void send_ruleset_nations(struct 
 }
 
 /**************************************************************************
-  Send nations availability information
-**************************************************************************/
-static void send_ruleset_nations_availability(struct conn_list *dest)
-{
-  int i;
-  for (i = 0; i < game.control.nation_count; i++) {
-    struct nation_type *nation = get_nation_by_idx(i);
-    struct packet_nation_available packet;
-    packet.id = i;
-    packet.is_unavailable = nation->is_unavailable;
-    packet.is_used = nation->is_used;
-    lsend_packet_nation_available(dest, &packet);
-  }
-}
-
-/**************************************************************************
   Send the city-style ruleset information (each style) to the specified
   connections.
 **************************************************************************/
@@ -3145,7 +3127,6 @@ void send_rulesets(struct conn_list *des
   send_ruleset_terrain(dest);
   send_ruleset_buildings(dest);
   send_ruleset_nations(dest);
-  send_ruleset_nations_availability(dest);
   send_ruleset_cities(dest);
   send_ruleset_cache(dest);
 
Index: server/ruleset.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.h,v
retrieving revision 1.9
diff -p -u -r1.9 ruleset.h
--- server/ruleset.h    18 Dec 2002 17:36:20 -0000      1.9
+++ server/ruleset.h    26 Aug 2005 21:37:37 -0000
@@ -18,4 +18,6 @@ struct conn_list;
 void load_rulesets(void);
 void send_rulesets(struct conn_list *dest);
 
+void send_ruleset_nations(struct conn_list *dest);
+
 #endif  /* FC__RULESET_H */
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.73
diff -p -u -r1.73 sanitycheck.c
--- server/sanitycheck.c        25 Aug 2005 19:21:20 -0000      1.73
+++ server/sanitycheck.c        26 Aug 2005 21:37:37 -0000
@@ -464,6 +464,10 @@ static void check_players(void)
     /* Dying players shouldn't be left around.  But they are. */
     SANITY_CHECK(!pplayer->is_dying);
   }
+
+  nations_iterate(pnation) {
+    SANITY_CHECK(!pnation->player || pnation->player->nation == pnation);
+  } nations_iterate_end;
 }
 
 /****************************************************************************
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.288
diff -p -u -r1.288 srv_main.c
--- server/srv_main.c   26 Aug 2005 19:40:26 -0000      1.288
+++ server/srv_main.c   26 Aug 2005 21:37:37 -0000
@@ -1164,20 +1164,6 @@ static bool is_allowed_player_name(struc
 }
 
 /****************************************************************************
-  Send unavailable/used information for this nation out to everyone.
-****************************************************************************/
-static void send_nation_available(struct nation_type *nation)
-{
-  struct packet_nation_available packet;
-
-  packet.id = nation->index;
-  packet.is_unavailable = nation->is_unavailable;
-  packet.is_used = nation->is_used;
-
-  lsend_packet_nation_available(game.est_connections, &packet);
-}
-
-/****************************************************************************
   Initialize the list of available nations.
 
   Call this on server start, or when loading a scenario.
@@ -1202,23 +1188,16 @@ void init_available_nations(void)
 
   if (start_nations) {
     nations_iterate(nation) {
-      nation->is_unavailable = TRUE;
+      nation->is_available = FALSE;
     } nations_iterate_end;
     for (i = 0; i < map.num_start_positions; i++) {
-      map.start_positions[i].nation->is_unavailable = FALSE;
+      map.start_positions[i].nation->is_available = TRUE;
     }
-  } else {
-    nations_iterate(nation) {
-      /* We preemptively mark unplayable nations as unavailable. */
-      /* FIXME: this may not be right since barbarians need them to be
-       * available (for instance). */
-      nation->is_unavailable = !is_nation_playable(nation);
-    } nations_iterate_end;
   }
   nations_iterate(nation) {
-    nation->is_used = FALSE;
-    send_nation_available(nation);
+    nation->player = NULL;
   } nations_iterate_end;
+  send_ruleset_nations(game.est_connections);
 }
 
 /**************************************************************************
@@ -1252,13 +1231,13 @@ void handle_nation_select_req(struct pla
       return;
     }
 
-    if (new_nation->is_unavailable) {
+    if (!new_nation->is_available) {
       notify_conn_ex(pplayer->connections, NULL, E_NATION_SELECTED,
                     _("%s nation is not available in this scenario."),
                     new_nation->name);
       return;
     }
-    if (new_nation->is_unavailable) {
+    if (new_nation->player && new_nation->player != pplayer) {
       notify_conn_ex(pplayer->connections, NULL, E_NATION_SELECTED,
                     _("%s nation is already in use."),
                     new_nation->name);
@@ -1283,17 +1262,13 @@ void handle_nation_select_req(struct pla
     sz_strlcpy(pplayer->name, name);
     pplayer->is_male = is_male;
     pplayer->city_style = city_style;
-
-    new_nation->is_used = TRUE;
-    send_nation_available(new_nation);
   }
 
-  pplayer->nation = new_nation; /* May be NULL (NO_NATION_SELECTED) */
+  (void) player_set_nation(pplayer, new_nation);
   send_player_info_c(pplayer, game.est_connections);
 
   if (old_nation != NO_NATION_SELECTED) {
-    old_nation->is_used = FALSE;
-    send_nation_available(old_nation);
+    old_nation->player = NULL;
   }
 }
 
@@ -1387,7 +1362,7 @@ void aifill(int amount)
     char player_name[ARRAY_SIZE(pplayer->name)];
 
     server_player_init(pplayer, FALSE, TRUE);
-    pplayer->nation = NO_NATION_SELECTED;
+    player_set_nation(pplayer, NULL);
     do {
       my_snprintf(player_name, sizeof(player_name),
                  "AI%d", ++filled);
@@ -1454,9 +1429,10 @@ static void generate_players(void)
     /* See if the player name matches a known leader name. */
     nations_iterate(pnation) {
       if (is_nation_playable(pnation)
-         && !pnation->is_unavailable && !pnation->is_used
+         && pnation->is_available
+         && !pnation->player
          && check_nation_leader_name(pnation, pplayer->name)) {
-       pplayer->nation = pnation;
+       player_set_nation(pplayer, pnation);
        pplayer->city_style = get_nation_city_style(pnation);
        pplayer->is_male = get_nation_leader_sex(pnation, pplayer->name);
        break;
@@ -1467,10 +1443,9 @@ static void generate_players(void)
       continue;
     }
 
-    pplayer->nation = pick_available_nation(NULL);
+    player_set_nation(pplayer, pick_available_nation(NULL));
     assert(pplayer->nation != NO_NATION_SELECTED);
 
-    pplayer->nation->is_used = TRUE;
     pplayer->city_style = get_nation_city_style(pplayer->nation);
 
     pick_random_player_name(pplayer->nation, player_name);

[Prev in Thread] Current Thread [Next in Thread]