Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2005:
[Freeciv-Dev] (PR#13145) completely new design for teams
Home

[Freeciv-Dev] (PR#13145) completely new design for teams

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#13145) completely new design for teams
From: "Jason Dorje Short" <jdorje@xxxxxxxxx>
Date: Thu, 19 May 2005 14:50:09 -0700
Reply-to: bugs@xxxxxxxxxxx

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

As discussed on IRC, this patch implements an entirely new design for teams.

Currently teams and team names are created on demand.  A player has a
team #, or "no team".  If you /team player-name team-name the new team
is named on the spot if it doesn't exist.  The problem is we want to
integrate teams into the GUI and this is basically impossible if they
aren't enumerated in any way.

In the new design, all teams are allocated at initialization time and
all names are pre-set.  (Currently the team names are listed in team.c
but eventually they should come from the ruleset.)  Every player
(including barbarians and dead players) is on a team.  When a new player
is created they are automatically put on the first empty team.

The /team command is made much simpler, since we don't have to create
new teams on the fly.  It looks first for a match to the team name, then
to a team number (the latter is mostly for debugging).

A new command /list teams is added.  This lists all teams with each
player on the team.  Rather useful.

No GUI support is added at this time.  Basically the GUI should simply
provide a drop-down menu for choosing a team.  Game hosts should be
allowed to set anyone's team.

This patch needs more testing.

-jason

Index: ai/advdiplomacy.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdiplomacy.c,v
retrieving revision 1.78
diff -u -r1.78 advdiplomacy.c
--- ai/advdiplomacy.c   7 May 2005 13:31:55 -0000       1.78
+++ ai/advdiplomacy.c   19 May 2005 21:49:34 -0000
@@ -160,7 +160,7 @@
 static bool shared_vision_is_safe(struct player* pplayer,
                                   struct player* aplayer)
 {
-  if (pplayer->team != TEAM_NONE && pplayer->team == aplayer->team) {
+  if (pplayer->team && pplayer->team == aplayer->team) {
     return TRUE;
   }
   players_iterate(eplayer) {
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.224
diff -u -r1.224 aicity.c
--- ai/aicity.c 10 May 2005 19:08:54 -0000      1.224
+++ ai/aicity.c 19 May 2005 21:49:35 -0000
@@ -251,7 +251,7 @@
 
   /* Remove team members from the equation */
   players_iterate(aplayer) {
-    if (aplayer->team != TEAM_NONE
+    if (aplayer->team
         && aplayer->team == pplayer->team
         && aplayer != pplayer) {
       nplayers--;
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.516
diff -u -r1.516 packhand.c
--- client/packhand.c   11 May 2005 20:03:07 -0000      1.516
+++ client/packhand.c   19 May 2005 21:49:35 -0000
@@ -1421,7 +1421,7 @@
   pplayer->is_observer = pinfo->is_observer;
   pplayer->nation=pinfo->nation;
   pplayer->is_male=pinfo->is_male;
-  pplayer->team = pinfo->team;
+  team_add_player(pplayer, team_get_by_id(pinfo->team));
   pplayer->score.game = pinfo->score;
 
   pplayer->economic.gold=pinfo->gold;
@@ -2013,8 +2013,6 @@
 **************************************************************************/
 void handle_ruleset_control(struct packet_ruleset_control *packet)
 {
-  int i;
-
   tileset_free_city_tiles(tileset, game.control.styles_count);
   ruleset_data_free();
 
@@ -2026,10 +2024,6 @@
   game.control.playable_nation_count = packet->playable_nation_count;
   city_styles_alloc(packet->styles_count);
   tileset_alloc_city_tiles(tileset, game.control.styles_count);
-  for(i = 0; i < MAX_NUM_TEAMS; i++) {
-    mystrlcpy(team_get_by_id(i)->name, packet->team_name[i],
-              MAX_LEN_NAME);
-  }
 }
 
 /**************************************************************************
Index: client/plrdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/plrdlg_common.c,v
retrieving revision 1.20
diff -u -r1.20 plrdlg_common.c
--- client/plrdlg_common.c      5 May 2005 20:26:13 -0000       1.20
+++ client/plrdlg_common.c      19 May 2005 21:49:36 -0000
@@ -97,11 +97,7 @@
 *******************************************************************/
 static const char *col_team(const struct player *player)
 {
-  if (player->team != TEAM_NONE) {
-    return team_get_by_id(player->team)->name;
-  } else {
-    return "";
-  }
+  return _(player->team->name);
 }
 
 /******************************************************************
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.248
diff -u -r1.248 capstr.c
--- common/capstr.c     19 May 2005 16:58:23 -0000      1.248
+++ common/capstr.c     19 May 2005 21:49:36 -0000
@@ -82,7 +82,7 @@
  *     as long as possible.  We want to maintain network compatibility with
  *     the stable branch for as long as possible.
  */
-#define CAPABILITY "+Freeciv.Devel.2005.May.19"
+#define CAPABILITY "+Freeciv.Devel.2005.May.19-2"
 
 void init_our_capability(void)
 {
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.215
diff -u -r1.215 game.c
--- common/game.c       11 May 2005 14:11:20 -0000      1.215
+++ common/game.c       19 May 2005 21:49:36 -0000
@@ -280,6 +280,7 @@
   techs_init();
   unit_types_init();
   specialists_init();
+  teams_init();
   idex_init();
   cm_init();
   
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.125
diff -u -r1.125 packets.def
--- common/packets.def  11 May 2005 20:03:08 -0000      1.125
+++ common/packets.def  19 May 2005 21:49:36 -0000
@@ -1252,8 +1252,6 @@
   UINT8 styles_count;
   UINT8 terrain_count;
   UINT8 num_specialist_types;
-
-  STRING team_name[MAX_NUM_TEAMS][MAX_LEN_NAME];
 end
 
 
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.181
diff -u -r1.181 player.c
--- common/player.c     7 May 2005 14:03:52 -0000       1.181
+++ common/player.c     19 May 2005 21:49:36 -0000
@@ -107,7 +107,7 @@
   sz_strlcpy(plr->username, ANON_USER_NAME);
   plr->is_male = TRUE;
   plr->nation = NO_NATION_SELECTED;
-  plr->team = TEAM_NONE;
+  plr->team = NULL;
   plr->is_started = FALSE;
   plr->revolution_finishes = -1;
   plr->capital = FALSE;
@@ -666,10 +666,7 @@
 bool players_on_same_team(const struct player *pplayer1,
                           const struct player *pplayer2)
 {
-  if (pplayer1->team == TEAM_NONE) {
-    return FALSE;
-  }
-  return (pplayer1->team == pplayer2->team);
+  return (pplayer1->team && pplayer1->team == pplayer2->team);
 }
 
 bool is_barbarian(const struct player *pplayer)
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.152
diff -u -r1.152 player.h
--- common/player.h     5 May 2005 20:26:13 -0000       1.152
+++ common/player.h     19 May 2005 21:49:36 -0000
@@ -194,7 +194,7 @@
   int government;
   int target_government;
   Nation_type_id nation;
-  Team_type_id team;
+  struct team *team;
   bool is_started; /* Did the player click "start" yet? */
   bool phase_done;
   int nturns_idle;
Index: common/team.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/team.c,v
retrieving revision 1.1
diff -u -r1.1 team.c
--- common/team.c       17 May 2005 23:01:22 -0000      1.1
+++ common/team.c       19 May 2005 21:49:36 -0000
@@ -18,6 +18,7 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "fcintl.h"
 #include "shared.h"
 #include "support.h"
 
@@ -29,23 +30,23 @@
    Functions for handling teams.
 ***********************************************************************/
 
-static struct team teams[MAX_NUM_TEAMS];
+struct team teams[MAX_NUM_TEAMS];
 
 /****************************************************************************
   Returns the id of a team given its name, or TEAM_NONE if 
   not found.
 ****************************************************************************/
-Team_type_id team_find_by_name(const char *team_name)
+struct team *team_find_by_name(const char *team_name)
 {
   assert(team_name != NULL);
 
   team_iterate(pteam) {
     if (mystrcasecmp(team_name, pteam->name) == 0) {
-      return pteam->id;
+      return pteam;
     }
   } team_iterate_end;
 
-  return TEAM_NONE;
+  return NULL;
 }
 
 /****************************************************************************
@@ -53,85 +54,119 @@
 ****************************************************************************/
 struct team *team_get_by_id(Team_type_id id)
 {
-  assert(id == TEAM_NONE || (id < MAX_NUM_TEAMS && id >= 0));
-  if (id == TEAM_NONE) {
+  if (id < 0 || id >= MAX_NUM_TEAMS) {
     return NULL;
   }
   return &teams[id];
 }
 
 /****************************************************************************
-  Set a player to a team. Removes previous team affiliation,
-  creates a new team if it does not exist.
+  Set a player to a team.  Removes the previous team affiliation if
+  necessary.
 ****************************************************************************/
-void team_add_player(struct player *pplayer, const char *team_name)
+void team_add_player(struct player *pplayer, struct team *pteam)
 {
-  Team_type_id team_id, i;
+  assert(pplayer != NULL && pteam != NULL);
+  assert(&teams[pteam->index] == pteam);
 
-  assert(pplayer != NULL && team_name != NULL);
-
-  /* find or create team */
-  team_id = team_find_by_name(team_name);
-  if (team_id == TEAM_NONE) {
-    /* see if we have another team available */
-    for (i = 0; i < MAX_NUM_TEAMS; i++) {
-      if (teams[i].id == TEAM_NONE) {
-        team_id = i;
-        break;
-      }
-    }
-    /* check if too many teams */
-    if (team_id == TEAM_NONE) {
-      die("Impossible: Too many teams!");
-    }
-    /* add another team */
-    teams[team_id].id = team_id;
-    sz_strlcpy(teams[team_id].name, team_name);
+  /* Remove the player from the old team, if any.  The player's team should
+   * only be NULL for a few instants after the player was created; after
+   * that they should automatically be put on a team.  So although we
+   * check for a NULL case here this is only needed for that one
+   * situation. */
+  if (pplayer->team) {
+    team_remove_player(pplayer);
   }
-  pplayer->team = team_id;
+
+  /* Put the player on the new team. */
+  pplayer->team = pteam;
+  pteam->players++;
+  assert(pteam->players <= MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
 }
 
 /****************************************************************************
-  Removes a player from a team, and removes the team if empty of
-  players
+  Remove the player from the team.  This should only be called when deleting
+  a player; since every player must always be on a team.
 ****************************************************************************/
 void team_remove_player(struct player *pplayer)
 {
-  bool others = FALSE;
+  pplayer->team->players--;
+  assert(pplayer->team->players >= 0);
+  pplayer->team = NULL;
+}
 
-  if (pplayer->team == TEAM_NONE) {
-    return;
-  }
+/****************************************************************************
+  Returns the most empty team available.  This is the team that should be
+  assigned to a newly-created player.
+****************************************************************************/
+struct team *find_empty_team(void)
+{
+  Team_type_id i;
+  /* Can't use teams_iterate here since it skips empty teams! */
+  struct team *pbest = NULL;
 
-  assert(pplayer->team < MAX_NUM_TEAMS && pplayer->team >= 0);
+  for (i = 0; i < MAX_NUM_TEAMS; i++) {
+    struct team *pteam = team_get_by_id(i);
 
-  /* anyone else using my team? */
-  players_iterate(aplayer) {
-    if (aplayer->team == pplayer->team && aplayer != pplayer) {
-      others = TRUE;
-      break;
+    if (!pbest || pbest->players > pteam->players) {
+      pbest = pteam;
+    }
+    if (pbest->players == 0) {
+      /* No need to keep looking. */
+      return pbest;
     }
-  } players_iterate_end;
-
-  /* no other team members left? remove team! */
-  if (!others) {
-    teams[pplayer->team].id = TEAM_NONE;
   }
-  pplayer->team = TEAM_NONE;
+
+  return pbest;
 }
 
 /****************************************************************************
   Initializes team structure
 ****************************************************************************/
-void team_init(void)
+void teams_init(void)
 {
   Team_type_id i;
-
-  assert(TEAM_NONE < 0 || TEAM_NONE >= MAX_NUM_TEAMS);
+  char *names[] = {
+    N_("Team 1"),
+    N_("Team 2"),
+    N_("Team 3"),
+    N_("Team 4"),
+    N_("Team 5"),
+    N_("Team 6"),
+    N_("Team 7"),
+    N_("Team 8"),
+    N_("Team 9"),
+    N_("Team 10"),
+    N_("Team 11"),
+    N_("Team 12"),
+    N_("Team 13"),
+    N_("Team 14"),
+    N_("Team 15"),
+    N_("Team 16"),
+    N_("Team 17"),
+    N_("Team 18"),
+    N_("Team 19"),
+    N_("Team 20"),
+    N_("Team 21"),
+    N_("Team 22"),
+    N_("Team 23"),
+    N_("Team 24"),
+    N_("Team 25"),
+    N_("Team 26"),
+    N_("Team 27"),
+    N_("Team 28"),
+    N_("Team 29"),
+    N_("Team 30"),
+    N_("Team 31"),
+    N_("Team 32"),
+  };
+  assert(ARRAY_SIZE(names) == MAX_NUM_TEAMS);
 
   for (i = 0; i < MAX_NUM_TEAMS; i++) {
     /* mark as unused */
-    teams[i].id = TEAM_NONE;
-    teams[i].name[0] = '\0';
+    teams[i].index = i;
+    sz_strlcpy(teams[i].name, names[i]);
+
+    teams[i].players = 0;
   }
 }
Index: common/team.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/team.h,v
retrieving revision 1.1
diff -u -r1.1 team.h
--- common/team.h       17 May 2005 23:01:22 -0000      1.1
+++ common/team.h       19 May 2005 21:49:36 -0000
@@ -16,20 +16,23 @@
 
 #include "fc_types.h"
 
-#define MAX_NUM_TEAMS MAX_NUM_PLAYERS
-#define TEAM_NONE 255
+#define MAX_NUM_TEAMS (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS)
 
 struct team {
-  Team_type_id id; /* equal to array index if active, else TEAM_NONE */
+  Team_type_id index;
   char name[MAX_LEN_NAME];
+
+  int players; /* # of players on the team */
 };
 
-void team_init(void);
-Team_type_id team_find_by_name(const char *team_name);
+void teams_init(void);
+struct team *team_find_by_name(const char *team_name);
 struct team *team_get_by_id(Team_type_id id);
-void team_add_player(struct player *pplayer, const char *team_name);
+void team_add_player(struct player *pplayer, struct team *pteam);
 void team_remove_player(struct player *pplayer);
 
+struct team *find_empty_team(void);
+
 #define team_iterate(pteam)                                                 \
 {                                                                           \
   struct team *pteam;                                                       \
@@ -37,7 +40,7 @@
                                                                            \
   for (PI_p_itr = 0; PI_p_itr < MAX_NUM_TEAMS; PI_p_itr++) {                \
     pteam = team_get_by_id(PI_p_itr);                                       \
-    if (pteam->id == TEAM_NONE) {                                           \
+    if (pteam->players == 0) {                                             \
       continue;                                                             \
     }
 
Index: server/commands.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/commands.c,v
retrieving revision 1.11
diff -u -r1.11 commands.c
--- server/commands.c   5 May 2005 20:26:14 -0000       1.11
+++ server/commands.c   19 May 2005 21:49:37 -0000
@@ -57,9 +57,10 @@
   {"list",     ALLOW_INFO,
    "list\n"
    "list players\n"
+   "list teams\n"
    "list connections",
-   N_("Show a list of players or connections."),
-   N_("Show a list of players, or a list of connections to the server.  "
+   N_("Show a list of players, teams, or connections."),
+   N_("Show a list of players, of teams, or of connections to the server.  "
       "The argument may be abbreviated, and defaults to 'players' if absent.")
   },
   {"quit",     ALLOW_HACK,
Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.47
diff -u -r1.47 connecthand.c
--- server/connecthand.c        6 May 2005 03:23:55 -0000       1.47
+++ server/connecthand.c        19 May 2005 21:49:37 -0000
@@ -675,6 +675,7 @@
       return FALSE; 
     } else {
       pplayer = &game.players[game.info.nplayers];
+      server_player_init(pplayer, FALSE);
       game.info.nplayers++;
     }
   }
Index: server/gamelog.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamelog.c,v
retrieving revision 1.49
diff -u -r1.49 gamelog.c
--- server/gamelog.c    5 May 2005 20:26:14 -0000       1.49
+++ server/gamelog.c    19 May 2005 21:49:37 -0000
@@ -497,9 +497,9 @@
     pteam = va_arg(args, struct team *);
 
     my_snprintf(buf, sizeof(buf), "<id>%d</id><name>%s</name>",
-                                  pteam->id, pteam->name);
+                                  pteam->index, pteam->name);
     players_iterate(aplayer) {
-      if (aplayer->team == pteam->id) {
+      if (aplayer->team == pteam) {
         cat_snprintf(buf, sizeof(buf), "<n>%d</n>", aplayer->player_no);
       }
     } players_iterate_end;
@@ -546,7 +546,7 @@
       pteam = va_arg(args, struct team *);
       my_snprintf(buf, sizeof(buf), "<type>%s</type>", endgame_strings[num]);
       players_iterate(aplayer) {
-        if (aplayer->team == pteam->id) {
+        if (aplayer->team == pteam) {
           cat_snprintf(buf, sizeof(buf), "<n>%d</n>", aplayer->player_no);
         }
       } players_iterate_end;
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.377
diff -u -r1.377 plrhand.c
--- server/plrhand.c    11 May 2005 14:57:10 -0000      1.377
+++ server/plrhand.c    19 May 2005 21:49:37 -0000
@@ -220,7 +220,7 @@
   cancel_all_meetings(pplayer);
 
   /* Show entire map for players who are *not* in a team. */
-  if (pplayer->team == TEAM_NONE) {
+  if (pplayer->team) {
     map_know_and_see_all(pplayer);
   }
 
@@ -1452,7 +1452,7 @@
   packet->nation=plr->nation;
   packet->is_male=plr->is_male;
   packet->is_observer=plr->is_observer;
-  packet->team = plr->team;
+  packet->team = plr->team->index;
   packet->is_started = plr->is_started;
   packet->city_style=plr->city_style;
 
@@ -1658,6 +1658,7 @@
     player_map_allocate(pplayer);
   }
   pplayer->player_no = pplayer - game.players;
+  team_add_player(pplayer, find_empty_team());
   ai_data_init(pplayer);
 }
 
@@ -1687,6 +1688,7 @@
     }
   } conn_list_iterate_end;
 
+  team_remove_player(pplayer);
   game_remove_player(pplayer);
   game_renumber_players(pplayer->player_no);
 }
@@ -2088,7 +2090,7 @@
   BV_CLR_ALL(pplayer->embassy);   /* all embassies destroyed */
 
   /* give splitted player the embassies to his team mates back, if any */
-  if (pplayer->team != TEAM_NONE) {
+  if (pplayer->team) {
     players_iterate(pdest) {
       if (pplayer->team == pdest->team
           && pplayer != pdest) {
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.248
diff -u -r1.248 savegame.c
--- server/savegame.c   10 May 2005 17:27:09 -0000      1.248
+++ server/savegame.c   19 May 2005 21:49:38 -0000
@@ -1730,15 +1730,9 @@
   init_tech(plr, 0);
 
   /* not all players have teams */
-  if (section_file_lookup(file, "player%d.team", plrno)) {
-    char tmp[MAX_LEN_NAME];
+  id = secfile_lookup_int_default(file, -1, "player%d.team_no", plrno);
+  plr->team = team_get_by_id(id);
 
-    sz_strlcpy(tmp, secfile_lookup_str(file, "player%d.team", plrno));
-    team_add_player(plr, tmp);
-    plr->team = team_find_by_name(tmp);
-  } else {
-    plr->team = TEAM_NONE;
-  }
   if (is_barbarian(plr)) {
     plr->nation = game.control.nation_count - 1;
   }
@@ -2543,10 +2537,8 @@
    * This field is kept only for forward compatibility
    * Nations can't be saved correctly because race must be < 62 */
   secfile_insert_int(file, plrno, "player%d.race", plrno);
-  if (plr->team != TEAM_NONE) {
-    secfile_insert_str(file, (char *) team_get_by_id(plr->team)->name, 
-                       "player%d.team", plrno);
-  }
+
+  secfile_insert_int(file, plr->team->index, "player%d.team_no", plrno);
 
   gov = get_government(plr->government);
   secfile_insert_str(file, gov->name_orig, "player%d.government_name", plrno);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.261
diff -u -r1.261 srv_main.c
--- server/srv_main.c   19 May 2005 16:57:30 -0000      1.261
+++ server/srv_main.c   19 May 2005 21:49:38 -0000
@@ -186,9 +186,6 @@
   srvarg.auth_allow_guests = FALSE;
   srvarg.auth_allow_newusers = FALSE;
 
-  /* initialize teams */
-  team_init();
-
   /* mark as initialized */
   has_been_srv_init = TRUE;
 
@@ -255,7 +252,7 @@
     players_iterate(pplayer) {
       if (pplayer->is_alive
           && !pplayer->surrendered
-          && pplayer->team != pteam->id) {
+          && pplayer->team != pteam) {
         win = FALSE;
         break;
       }
@@ -1365,7 +1362,7 @@
 {
   Nation_type_id nation;
   char player_name[MAX_LEN_NAME];
-  int i, old_nplayers;
+  int i;
 
   /* Select nations for AI players generated with server
    * 'create <name>' command
@@ -1439,16 +1436,16 @@
   }
 
   for(;game.info.nplayers < game.aifill + i;) {
-    struct player *pplayer;
+    const int old_nplayers = game.info.nplayers;
+    struct player *pplayer = get_player(old_nplayers);
+
+    server_player_init(pplayer, FALSE);
 
     nation = select_random_nation();
     assert(nation != NO_NATION_SELECTED);
     get_nation_by_idx(nation)->is_used = TRUE;
     pick_random_player_name(nation, player_name);
 
-    old_nplayers = game.info.nplayers;
-    pplayer = get_player(old_nplayers);
-     
     sz_strlcpy(pplayer->name, player_name);
     sz_strlcpy(pplayer->username, ANON_USER_NAME);
 
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.410
diff -u -r1.410 stdinhand.c
--- server/stdinhand.c  19 May 2005 16:58:23 -0000      1.410
+++ server/stdinhand.c  19 May 2005 21:49:41 -0000
@@ -80,6 +80,7 @@
                                   bool check);
 static bool show_help(struct connection *caller, char *arg);
 static bool show_list(struct connection *caller, char *arg);
+static void show_teams(struct connection *caller);
 static void show_connections(struct connection *caller);
 static bool set_ai_level(struct connection *caller, char *name, int level, 
                          bool check);
@@ -955,7 +956,6 @@
   }
 
   sz_strlcpy(name, pplayer->name);
-  team_remove_player(pplayer);
   server_remove_player(pplayer);
   if (!caller || caller->used) {     /* may have removed self */
     cmd_reply(CMD_REMOVE, caller, C_OK,
@@ -2047,6 +2047,7 @@
   char *arg[2];
   int ntokens = 0, i;
   bool res = FALSE;
+  struct team *pteam;
 
   if (server_state != PRE_GAME_STATE) {
     cmd_reply(CMD_TEAM, caller, C_SYNTAX,
@@ -2058,9 +2059,9 @@
     sz_strlcpy(buf, str);
     ntokens = get_tokens(buf, arg, 2, TOKEN_DELIMITERS);
   }
-  if (ntokens > 2 || ntokens < 1) {
+  if (ntokens != 2) {
     cmd_reply(CMD_TEAM, caller, C_SYNTAX,
-             _("Undefined argument.  Usage: team <player> [team]."));
+             _("Undefined argument.  Usage: team <player> <team>."));
     goto cleanup;
   }
 
@@ -2070,34 +2071,30 @@
     goto cleanup;
   }
 
-  if (!check && pplayer->team != TEAM_NONE) {
-    team_remove_player(pplayer);
-  }
+  pteam = team_find_by_name(arg[1]);
+  if (!pteam) {
+    int teamno;
 
-  if (ntokens == 1) {
-    /* Remove from team */
-    if (!check) {
-      cmd_reply(CMD_TEAM, caller, C_OK, _("Player %s is made teamless."), 
-          pplayer->name);
+    if (sscanf(arg[1], "%d", &teamno) == 1) {
+      pteam = team_get_by_id(teamno);
     }
-    res = TRUE;
-    goto cleanup;
   }
-
-  if (!is_ascii_name(arg[1])) {
+  if (!pteam) {
     cmd_reply(CMD_TEAM, caller, C_SYNTAX,
-             _("Only ASCII characters are allowed for team names."));
+             _("No such team %s.  Please give a "
+               "valid team name or number."), arg[1]);
     goto cleanup;
   }
+
   if (is_barbarian(pplayer)) {
     /* This can happen if we change team settings on a loaded game. */
     cmd_reply(CMD_TEAM, caller, C_SYNTAX, _("Cannot team a barbarian."));
     goto cleanup;
   }
   if (!check) {
-    team_add_player(pplayer, arg[1]);
+    team_add_player(pplayer, pteam);
     cmd_reply(CMD_TEAM, caller, C_OK, _("Player %s set to team %s."),
-             pplayer->name, team_get_by_id(pplayer->team)->name);
+             pplayer->name, _(pteam->name));
   }
   res = TRUE;
 
@@ -3884,10 +3881,14 @@
 /**************************************************************************
   'list' arguments
 **************************************************************************/
-enum LIST_ARGS { LIST_PLAYERS, LIST_CONNECTIONS,
-                LIST_ARG_NUM /* Must be last */ };
+enum LIST_ARGS {
+  LIST_PLAYERS,
+  LIST_TEAMS,
+  LIST_CONNECTIONS,
+  LIST_ARG_NUM /* Must be last */
+};
 static const char * const list_args[] = {
-  "players", "connections", NULL
+  "players", "teams", "connections", NULL
 };
 static const char *listarg_accessor(int i) {
   return list_args[i];
@@ -3899,11 +3900,13 @@
 static bool show_list(struct connection *caller, char *arg)
 {
   enum m_pre_result match_result;
-  int ind;
+  int ind_int;
+  enum LIST_ARGS ind;
 
   remove_leading_trailing_spaces(arg);
   match_result = match_prefix(listarg_accessor, LIST_ARG_NUM, 0,
-                             mystrncasecmp, arg, &ind);
+                             mystrncasecmp, arg, &ind_int);
+  ind = ind_int;
 
   if (match_result > M_PRE_EMPTY) {
     cmd_reply(CMD_LIST, caller, C_SYNTAX,
@@ -3920,15 +3923,20 @@
   case LIST_PLAYERS:
     show_players(caller);
     return TRUE;
+  case LIST_TEAMS:
+    show_teams(caller);
+    return TRUE;
   case LIST_CONNECTIONS:
     show_connections(caller);
     return TRUE;
-  default:
-    cmd_reply(CMD_LIST, caller, C_FAIL,
-             "Internal error: ind %d in show_list", ind);
-    freelog(LOG_ERROR, "Internal error: ind %d in show_list", ind);
-    return FALSE;
+  case LIST_ARG_NUM:
+    break;
   }
+
+  cmd_reply(CMD_LIST, caller, C_FAIL,
+           "Internal error: ind %d in show_list", ind);
+  freelog(LOG_ERROR, "Internal error: ind %d in show_list", ind);
+  return FALSE;
 }
 
 /**************************************************************************
@@ -3982,10 +3990,8 @@
        cat_snprintf(buf2, sizeof(buf2), _(", nation %s"),
                     get_nation_name_plural(pplayer->nation));
       }
-      if (pplayer->team != TEAM_NONE) {
-        cat_snprintf(buf2, sizeof(buf2), _(", team %s"),
-                     team_get_by_id(pplayer->team)->name);
-      }
+      cat_snprintf(buf2, sizeof(buf2), _(", team %s"),
+                  pplayer->team->name);
       if (server_state == PRE_GAME_STATE && pplayer->is_connected) {
        if (pplayer->is_started) {
          cat_snprintf(buf2, sizeof(buf2), _(", ready"));
@@ -4019,6 +4025,55 @@
 }
 
 /**************************************************************************
+  Show a list of teams on the command line.
+**************************************************************************/
+static void show_teams(struct connection *caller)
+{
+  Team_type_id team_no;
+
+  /* Currently this just lists all teams (typically 32 of them) with their
+   * names and # of players on the team.  This could probably be improved. */
+  cmd_reply(CMD_LIST, caller, C_COMMENT, _("List of teams:"));
+  cmd_reply(CMD_LIST, caller, C_COMMENT, horiz_line);
+  for (team_no = 0; team_no < MAX_NUM_TEAMS; team_no++) {
+    struct team *pteam = team_get_by_id(team_no);
+
+    if (pteam->players > 1) {
+      /* PL_() is needed here because some languages may differentiate
+       * between 2 and 3 (although English does not). */
+      cmd_reply(CMD_LIST, caller, C_COMMENT,
+               /* TRANS: There will always be at least 2 players here. */
+               PL_("%2d : '%s' : %d player",
+                   "%2d : '%s' : %d players",
+                   pteam->players),
+               team_no, _(pteam->name), pteam->players);
+      players_iterate(pplayer) {
+       if (pplayer->team == pteam) {
+         cmd_reply(CMD_LIST, caller, C_COMMENT, "  %s", pplayer->name);
+       }
+      } players_iterate_end;
+    } else if (pteam->players == 1) {
+      struct player *teamplayer = NULL;
+
+      players_iterate(pplayer) {
+       if (pplayer->team == pteam) {
+         teamplayer = pplayer;
+         break;
+       }
+      } players_iterate_end;
+
+      cmd_reply(CMD_LIST, caller, C_COMMENT,
+               _("%2d : '%s' : 1 player : %s"),
+               team_no, _(pteam->name), teamplayer->name);
+    }
+  }
+  cmd_reply(CMD_LIST, caller, C_COMMENT, " ");
+  cmd_reply(CMD_LIST, caller, C_COMMENT,
+           _("Empty team: %s"), find_empty_team()->name);
+  cmd_reply(CMD_LIST, caller, C_COMMENT, horiz_line);
+}
+
+/**************************************************************************
   List connections; initially mainly for debugging
 **************************************************************************/
 static void show_connections(struct connection *caller)

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#13145) completely new design for teams, Jason Dorje Short <=