Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2005:
[Freeciv-Dev] Re: (PR#14522) Hotseat mode
Home

[Freeciv-Dev] Re: (PR#14522) Hotseat mode

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#14522) Hotseat mode
From: "Andreas Røsdal" <andrearo@xxxxxxxxxxxx>
Date: Fri, 4 Nov 2005 11:58:09 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Hi,

Here's an initial patch implementing hotseat mode for Freeciv, done pretty
much like I described in the previous mail.

There's a hotseat option, found under "internal" in the server settings,
to specify the number of local players. Timeout and Saving/loading is also
handled. And there's a screen between each phase.
I hope it's a little useful..

Andreas R.




diff -ruN -Xfreeciv/diff_ignore freeciv/client/civclient.c 
freeciv-hotseat/client/civclient.c
--- freeciv/client/civclient.c  2005-10-03 04:50:47.000000000 +0200
+++ freeciv-hotseat/client/civclient.c  2005-11-04 18:39:22.000000000 +0100
@@ -516,7 +516,9 @@
       can_slide = FALSE;
       update_unit_focus();
       can_slide = TRUE;
-      set_client_page(PAGE_GAME);
+      if (get_client_page() != PAGE_PHASE) {
+        set_client_page(PAGE_GAME);
+      }
     }
     else if (client_state == CLIENT_PRE_GAME_STATE) {
       popdown_all_city_dialogs();
@@ -530,7 +532,7 @@
       client_game_init();
       if (!aconnection.established) {
        set_client_page(PAGE_MAIN);
-      } else {
+      } else if (!game.info.hotseat) {
        set_client_page(PAGE_START);
       }
     }
diff -ruN -Xfreeciv/diff_ignore freeciv/client/connectdlg_common.c 
freeciv-hotseat/client/connectdlg_common.c
--- freeciv/client/connectdlg_common.c  2005-10-25 23:24:09.000000000 +0200
+++ freeciv-hotseat/client/connectdlg_common.c  2005-11-04 19:59:48.000000000 
+0100
@@ -509,10 +509,13 @@
   char buf[MAX_LEN_MSG];
 
   send_chat("/set timeout 0");
-  send_chat("/set autotoggle 1");
-  my_snprintf(buf, sizeof(buf), "/take \"%s\" \"%s\"",
-             user_name, player_name);
-  send_chat(buf);
+  if (!game.info.hotseat) {
+    send_chat("/set autotoggle 1");
+    my_snprintf(buf, sizeof(buf), "/take \"%s\" \"%s\"",
+               user_name, player_name);
+    send_chat(buf);
+  }
+  
   send_chat("/start");
 }
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/gui_main.c 
freeciv-hotseat/client/gui-gtk-2.0/gui_main.c
--- freeciv/client/gui-gtk-2.0/gui_main.c       2005-10-17 22:04:30.000000000 
+0200
+++ freeciv-hotseat/client/gui-gtk-2.0/gui_main.c       2005-11-04 
18:39:22.000000000 +0100
@@ -754,6 +754,8 @@
       create_network_page(), NULL);
   gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
       create_nation_page(), NULL);
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+      create_phase_page(), NULL);
 
   main_tips = gtk_tooltips_new();
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/pages.c 
freeciv-hotseat/client/gui-gtk-2.0/pages.c
--- freeciv/client/gui-gtk-2.0/pages.c  2005-10-10 02:11:45.000000000 +0200
+++ freeciv-hotseat/client/gui-gtk-2.0/pages.c  2005-11-04 20:36:05.000000000 
+0100
@@ -56,6 +56,8 @@
 static GtkWidget *start_options_table;
 GtkWidget *ready_button;
 
+static GtkWidget *hotseat_label, *hotseat_message;
+
 static GtkWidget *scenario_description;
 
 static GtkListStore *load_store, *scenario_store,
@@ -1486,6 +1488,101 @@
   return box;
 }
 
+/**************************************************************************
+ Update the hotseat phase page with info about the next player.
+**************************************************************************/
+static void update_phase_page(void)
+{
+  char buf[512];
+  int nextphase = (game.info.phase + 1) % game.info.num_phases;
+
+  my_snprintf(buf, sizeof(buf), _("Hotseat Game - Year: %s"),
+                                 textyear(game.info.year));
+  gtk_label_set_text(GTK_LABEL(hotseat_label), buf);
+
+  my_snprintf(buf, sizeof(buf), _("Next Player: %s"),
+                               get_player(nextphase)->name);
+  gtk_label_set_text(GTK_LABEL(hotseat_message), buf);
+
+}
+
+/**************************************************************************
+  Activate next phas, after the user accepted the end of phase page.
+**************************************************************************/
+static void next_phase_callback(void)
+{
+  dsend_packet_player_begin_hotseat_phase(&aconnection, 
+                                   get_player(game.info.phase)->player_no);
+  set_client_page(PAGE_GAME);
+}
+
+/**************************************************************************
+  create the end of hotseat phase page.
+**************************************************************************/
+GtkWidget *create_phase_page(void)
+{
+  GtkWidget *align, *box, *frame, *image, *sbox, *bbox, *hbox;
+  GtkWidget *button;
+  GtkSizeGroup *size;
+
+  size = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
+
+  box = gtk_vbox_new(FALSE, 6);
+  gtk_container_set_border_width(GTK_CONTAINER(box), 4);
+
+  align = gtk_alignment_new(0.5, 0.0, 0.0, 0.0);
+  gtk_container_set_border_width(GTK_CONTAINER(align), 18);
+  gtk_box_pack_start(GTK_BOX(box), align, FALSE, FALSE, 0);
+
+  frame = gtk_frame_new(NULL);
+  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
+  gtk_container_add(GTK_CONTAINER(align), frame);
+
+  image = gtk_image_new_from_file(tileset_main_intro_filename(tileset));
+  g_signal_connect_after(image, "expose_event",
+                         G_CALLBACK(intro_expose), NULL);
+  gtk_container_add(GTK_CONTAINER(frame), image);
+
+  align = gtk_alignment_new(0.5, 0.0, 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(box), align, FALSE, FALSE, 0);
+
+  sbox = gtk_vbox_new(FALSE, 10);
+  gtk_container_add(GTK_CONTAINER(align), sbox);
+
+  bbox = gtk_vbox_new(FALSE, 6);
+  gtk_container_add(GTK_CONTAINER(sbox), bbox);
+
+  hotseat_label = gtk_label_new("");
+  gtk_size_group_add_widget(size, hotseat_label);
+  gtk_container_add(GTK_CONTAINER(bbox), hotseat_label);
+
+  hotseat_message = gtk_label_new("");
+  gtk_size_group_add_widget(size, hotseat_message);
+  gtk_container_add(GTK_CONTAINER(bbox), hotseat_message);
+
+  hbox = gtk_hbutton_box_new();
+  gtk_box_set_spacing(GTK_BOX(hbox), 12);
+  gtk_box_pack_start(GTK_BOX(bbox), hbox, FALSE, FALSE, 0);
+
+  button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
+  gtk_container_add(GTK_CONTAINER(hbox), button);
+  g_signal_connect(button, "clicked",
+      G_CALLBACK(gtk_main_quit), NULL);
+
+
+  button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
+  gtk_container_add(GTK_CONTAINER(hbox), button);
+  g_signal_connect(button, "clicked",
+      G_CALLBACK(popup_save_dialog), NULL);
+
+  button = gtk_button_new_from_stock(GTK_STOCK_OK);
+  gtk_container_add(GTK_CONTAINER(hbox), button);
+  g_signal_connect(button, "clicked",
+      G_CALLBACK(next_phase_callback), NULL);
+
+
+  return box;
+}
 
 /**************************************************************************
   Updates the info for the currently selected scenario.
@@ -1862,6 +1959,8 @@
   }
 
   switch (old_page) {
+  case PAGE_PHASE:
+    break;
   case PAGE_SCENARIO:
   case PAGE_LOAD:
     break;
@@ -1897,6 +1996,9 @@
   case PAGE_LOAD:
     update_load_page();
     break;
+  case PAGE_PHASE:
+    update_phase_page();
+    break;
   case PAGE_SCENARIO:
     update_scenario_page();
     break;
@@ -1930,6 +2032,8 @@
   case PAGE_LOAD:
     gtk_tree_view_focus(gtk_tree_selection_get_tree_view(load_selection));
     break;
+  case PAGE_PHASE:
+    break;
   case PAGE_SCENARIO:
     gtk_tree_view_focus(gtk_tree_selection_get_tree_view(scenario_selection));
     break;
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/pages.h 
freeciv-hotseat/client/gui-gtk-2.0/pages.h
--- freeciv/client/gui-gtk-2.0/pages.h  2005-06-01 03:02:34.000000000 +0200
+++ freeciv-hotseat/client/gui-gtk-2.0/pages.h  2005-11-04 18:39:22.000000000 
+0100
@@ -28,6 +28,7 @@
 GtkWidget *create_load_page(void);
 GtkWidget *create_network_page(void);
 GtkWidget *create_nation_page(void);
+GtkWidget *create_phase_page(void);
 
 GtkWidget *create_statusbar(void);
 void append_network_statusbar(const char *text, bool force);
diff -ruN -Xfreeciv/diff_ignore freeciv/client/include/pages_g.h 
freeciv-hotseat/client/include/pages_g.h
--- freeciv/client/include/pages_g.h    2005-09-26 20:59:12.000000000 +0200
+++ freeciv-hotseat/client/include/pages_g.h    2005-11-04 18:39:22.000000000 
+0100
@@ -23,6 +23,7 @@
   PAGE_LOAD,           /* Load saved game page. */
   PAGE_NETWORK,                /* Connect to network page.  */
   PAGE_NATION,         /* Select a nation page.  */
+  PAGE_PHASE,          /* End of hotseat phase page. */
   PAGE_GAME            /* In game page. */
 };
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/packhand.c 
freeciv-hotseat/client/packhand.c
--- freeciv/client/packhand.c   2005-11-02 07:40:39.000000000 +0100
+++ freeciv-hotseat/client/packhand.c   2005-11-04 19:49:12.000000000 +0100
@@ -832,6 +832,11 @@
    */
   game.info.turn++;
   agents_before_new_turn();
+  if (game.info.hotseat) {
+    set_client_page(PAGE_PHASE);
+    dsend_packet_player_end_hotseat_phase(&aconnection,
+                                          game.player_ptr->player_no);
+  }
 }
 
 /**************************************************************************
diff -ruN -Xfreeciv/diff_ignore freeciv/common/game.c 
freeciv-hotseat/common/game.c
--- freeciv/common/game.c       2005-10-15 00:45:28.000000000 +0200
+++ freeciv-hotseat/common/game.c       2005-11-04 18:39:22.000000000 +0100
@@ -249,6 +249,7 @@
 
   game.info.is_new_game   = TRUE;
   game.simultaneous_phases_stored = GAME_DEFAULT_SIMULTANEOUS_PHASES;
+  game.hotseat = GAME_DEFAULT_HOTSEAT_PLAYERS;
   game.timeoutint    = GAME_DEFAULT_TIMEOUTINT;
   game.timeoutintinc = GAME_DEFAULT_TIMEOUTINTINC;
   game.timeoutinc    = GAME_DEFAULT_TIMEOUTINC;
diff -ruN -Xfreeciv/diff_ignore freeciv/common/game.h 
freeciv-hotseat/common/game.h
--- freeciv/common/game.h       2005-10-31 14:13:23.000000000 +0100
+++ freeciv-hotseat/common/game.h       2005-11-04 18:39:22.000000000 +0100
@@ -69,6 +69,7 @@
    * use.  The "stored" value is a value the player can change; it won't
    * take effect until the next turn. */
   bool simultaneous_phases_stored;
+  int hotseat;
   char *startmessage;
   struct player *player_ptr; /* Client-only; may be NULL */
   struct player players[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
@@ -297,6 +298,8 @@
 
 #define GAME_DEFAULT_SIMULTANEOUS_PHASES TRUE
 
+#define GAME_DEFAULT_HOTSEAT_PLAYERS 0
+
 #define GAME_DEFAULT_TCPTIMEOUT      10
 #define GAME_MIN_TCPTIMEOUT          0
 #define GAME_MAX_TCPTIMEOUT          120
diff -ruN -Xfreeciv/diff_ignore freeciv/common/packets.def 
freeciv-hotseat/common/packets.def
--- freeciv/common/packets.def  2005-10-15 20:10:21.000000000 +0200
+++ freeciv-hotseat/common/packets.def  2005-11-04 19:48:57.000000000 +0100
@@ -361,6 +361,8 @@
   BOOL simultaneous_phases;
   UINT32 num_phases;
 
+  UINT32 hotseat;
+
   PLAYER min_players;
   PLAYER max_players;
   PLAYER nplayers;
@@ -703,6 +705,14 @@
   MEMORY data[ATTRIBUTE_CHUNK_SIZE:chunk_length];
 end
 
+PACKET_PLAYER_BEGIN_HOTSEAT_PHASE=125;cs,dsend
+  PLAYER player_no;
+end
+
+PACKET_PLAYER_END_HOTSEAT_PHASE=126;cs,dsend
+  PLAYER player_no;
+end
+
 /************** Unit packets **********************/
 
 PACKET_UNIT_REMOVE=48;sc,dsend,lsend
diff -ruN -Xfreeciv/diff_ignore freeciv/server/connecthand.c 
freeciv-hotseat/server/connecthand.c
--- freeciv/server/connecthand.c        2005-10-06 18:19:36.000000000 +0200
+++ freeciv-hotseat/server/connecthand.c        2005-11-04 20:43:08.000000000 
+0100
@@ -147,12 +147,21 @@
     gamelog(GAMELOG_PLAYER, pplayer);
 
   } else if (server_state == PRE_GAME_STATE && game.info.is_new_game) {
-    if (!attach_connection_to_player(pconn, NULL)) {
-      notify_conn(dest, NULL, E_CONNECTION,
-                 _("Couldn't attach your connection to new player."));
-      freelog(LOG_VERBOSE, "%s is not attached to a player", pconn->username);
+    if (game.info.hotseat && conn_list_size(game.est_connections) > 0) {
+        notify_conn(dest, NULL, E_CONNECTION,
+                    _("Can not attach your connection to new player, "
+                      "because a hotseat game is in progress."));
+        freelog(LOG_VERBOSE, "%s is not attached to a player",
+                             pconn->username);
     } else {
-      sz_strlcpy(pconn->player->name, pconn->username);
+      if (!attach_connection_to_player(pconn, NULL)) {
+        notify_conn(dest, NULL, E_CONNECTION,
+                   _("Couldn't attach your connection to new player."));
+        freelog(LOG_VERBOSE, "%s is not attached to a player", 
+                             pconn->username);
+      } else {
+        sz_strlcpy(pconn->player->name, pconn->username);
+      }
     }
   }
 
diff -ruN -Xfreeciv/diff_ignore freeciv/server/savegame.c 
freeciv-hotseat/server/savegame.c
--- freeciv/server/savegame.c   2005-10-24 06:33:05.000000000 +0200
+++ freeciv-hotseat/server/savegame.c   2005-11-04 18:53:48.000000000 +0100
@@ -3190,6 +3190,8 @@
       = secfile_lookup_bool_default(file, TRUE,
                                    "game.simultaneous_phases_stored");
 
+    game.info.hotseat = secfile_lookup_int_default(file, 0, "game.hotseat");
+    game.hotseat = secfile_lookup_int_default(file, 0, "game.hotseat");
     game.info.min_players   = secfile_lookup_int(file, "game.min_players");
     game.info.max_players   = secfile_lookup_int(file, "game.max_players");
 
@@ -3755,6 +3757,7 @@
   secfile_insert_int(file, game.info.end_year, "game.end_year");
   secfile_insert_int(file, game.info.year, "game.year");
   secfile_insert_int(file, game.info.turn, "game.turn");
+  secfile_insert_int(file, game.info.hotseat, "game.hotseat");
   secfile_insert_bool(file, game.info.simultaneous_phases,
                      "game.simultaneous_phases_now");
   secfile_insert_bool(file, game.simultaneous_phases_stored,
diff -ruN -Xfreeciv/diff_ignore freeciv/server/settings.c 
freeciv-hotseat/server/settings.c
--- freeciv/server/settings.c   2005-09-26 20:59:12.000000000 +0200
+++ freeciv-hotseat/server/settings.c   2005-11-04 18:39:22.000000000 +0100
@@ -22,6 +22,7 @@
 #include "map.h"
 
 #include "gamelog.h"
+#include "plrhand.h"
 #include "report.h"
 #include "settings.h"
 #include "srv_main.h"
@@ -172,6 +173,73 @@
   return TRUE;
 }
 
+/*************************************************************************
+  Initialize hotseat game.
+*************************************************************************/
+static bool hotseat_callback(int value, const char **error_string)
+{
+  int locals = 0;
+  game.simultaneous_phases_stored = FALSE;
+  game.hotseat = value;
+  game.info.hotseat = value;
+
+  if (game.info.aifill < value) {
+    aifill(value);
+  }
+
+  players_iterate(pplayer) {
+    if (!pplayer->ai.control) {
+      locals++;
+    }
+  } players_iterate_end;
+
+  /* Create the number of local players requested. */
+  if (locals < value) {
+    players_iterate(pplayer) {
+      if (locals != value && pplayer->ai.control)  {
+        toggle_ai_player_direct(NULL, pplayer);
+        pplayer->was_created = TRUE;
+        sz_strlcpy(pplayer->username, _("Local Player"));
+        send_player_info(pplayer, NULL);
+        locals++;
+      }
+    } players_iterate_end;
+  }
+
+  /* Remove the number of local players requrested. */
+  if (locals > value) {
+   players_iterate(pplayer) {
+      if (locals != value && !pplayer->ai.control 
+          && !pplayer->is_connected) {
+        toggle_ai_player_direct(NULL, pplayer);
+        sz_strlcpy(pplayer->username, ANON_PLAYER_NAME);
+        send_player_info(pplayer, NULL);
+        locals--;
+      }
+    } players_iterate_end;
+  }
+
+  error_string = NULL;
+  return TRUE;
+}
+
+/*************************************************************************
+  Verify the simultaneous phases option.
+*************************************************************************/
+static bool simultaneousphases_callback(bool value, const char **error)
+{
+  if (game.hotseat) {
+    *error =_("simultaneousphases can't be changed if the hotseat "
+                     "option is enabled.");
+    return FALSE;
+  }
+  game.simultaneous_phases_stored = value;
+  error = NULL;
+
+  return TRUE;
+}
+
+
 #define GEN_BOOL(name, value, sclass, scateg, slevel, to_client,       \
                 short_help, extra_help, func, default)                 \
   {name, sclass, to_client, short_help, extra_help, SSET_BOOL,         \
@@ -878,9 +946,20 @@
           N_("Whether to have simultaneous player phases."),
           N_("If true, all players' movement phases will occur "
              "simultaneously; if false then players will "
-             "alternate movement."), NULL,
+             "alternate movement."), simultaneousphases_callback,
           GAME_DEFAULT_SIMULTANEOUS_PHASES)
 
+  GEN_INT("hotseat", game.hotseat,
+           SSET_GAME_INIT, SSET_INTERNAL, SSET_SITUATIONAL, SSET_TO_CLIENT,
+           N_("Hotseat game with this number of local players"),
+           N_("Hotseat games allows multiple players to use "
+              "the same client to play alternating turns. "
+              "This value is set to the total number of local "
+              "players, while hotseat is disabled when set to 0. "
+              "Hotseat disables the option simultaneousphases."),
+               hotseat_callback, 0, 
+               GAME_MAX_MIN_PLAYERS, GAME_DEFAULT_HOTSEAT_PLAYERS)
+
   GEN_INT("nettimeout", game.info.tcptimeout,
          SSET_META, SSET_NETWORK, SSET_RARE, SSET_TO_CLIENT,
          N_("Seconds to let a client's network connection block"),
diff -ruN -Xfreeciv/diff_ignore freeciv/server/srv_main.c 
freeciv-hotseat/server/srv_main.c
--- freeciv/server/srv_main.c   2005-10-16 18:42:37.000000000 +0200
+++ freeciv-hotseat/server/srv_main.c   2005-11-04 20:43:26.000000000 +0100
@@ -572,9 +572,15 @@
 
   sanity_check();
 
-  game.info.seconds_to_phasedone = (double)game.info.timeout;
-  game.phase_timer = renew_timer_start(game.phase_timer,
-                                      TIMER_USER, TIMER_ACTIVE);
+  if (!game.info.hotseat || (!game.info.turn && !game.info.phase)) {
+    game.info.seconds_to_phasedone = (double)game.info.timeout;
+    game.phase_timer = renew_timer_start(game.phase_timer,
+                                        TIMER_USER, TIMER_ACTIVE);
+  } else {
+    game.info.seconds_to_phasedone = 0;
+    game.phase_timer = 0;
+  }
+
   send_game_info(NULL);
 }
 
@@ -1276,6 +1282,41 @@
 }
 
 /****************************************************************************
+  Handle a player begin phase packet. Only valid in hotseat games.
+  Reciving this packet (if valid), will begin the timeout.
+****************************************************************************/
+void handle_player_begin_hotseat_phase(struct player *requestor, 
+                                       int player_no)
+{
+  struct player *pplayer = get_player(player_no);
+
+  if (!game.info.hotseat || !pplayer || !requestor) {
+    return;
+  }
+
+  game.info.seconds_to_phasedone = (double)game.info.timeout;
+  game.phase_timer = renew_timer_start(game.phase_timer,
+                                       TIMER_USER, TIMER_ACTIVE);
+  send_game_info(NULL);
+}
+
+/****************************************************************************
+  Handles the packet to end a hotseat phase, which gives the connection
+  the next available player.
+****************************************************************************/
+void handle_player_end_hotseat_phase(struct player *requestor, int player_no)
+{
+  struct player *pplayer = get_player(player_no);
+
+  if (!game.info.hotseat || !requestor || !pplayer) {
+    return;
+  }
+
+  take_player_for_conn(requestor->current_conn, get_player(game.info.phase),
+                       requestor->current_conn); 
+}
+
+/****************************************************************************
   Handle a player-ready packet.
 ****************************************************************************/
 void handle_player_ready(struct player *requestor,
diff -ruN -Xfreeciv/diff_ignore freeciv/server/stdinhand.c 
freeciv-hotseat/server/stdinhand.c
--- freeciv/server/stdinhand.c  2005-11-02 18:17:47.000000000 +0100
+++ freeciv-hotseat/server/stdinhand.c  2005-11-04 20:11:00.000000000 +0100
@@ -2680,7 +2681,13 @@
   struct connection *pconn = NULL;
   struct player *pplayer = NULL;
   bool res = FALSE;
-  
+ 
+  if (game.info.hotseat) {
+    cmd_reply(CMD_OBSERVE, caller, C_FAIL,
+              _("The observe command is invalid when hotseat is enabled."));
+    goto end;
+  }  
+
   /******** PART I: fill pconn and pplayer ********/
 
   sz_strlcpy(buf, str);
@@ -2841,12 +2848,17 @@
 static bool take_command(struct connection *caller, char *str, bool check)
 {
   int i = 0, ntokens = 0;
-  char buf[MAX_LEN_CONSOLE_LINE], *arg[2], msg[MAX_LEN_MSG];
-  bool is_newgame = server_state == PRE_GAME_STATE && game.info.is_new_game;
+  char buf[MAX_LEN_CONSOLE_LINE], *arg[2];
   enum m_pre_result match_result;
   struct connection *pconn = NULL;
   struct player *pplayer = NULL;
   bool res = FALSE;
+
+  if (game.info.hotseat) {
+    cmd_reply(CMD_TAKE, caller, C_FAIL,
+              _("The take command is invalid when hotseat is enabled."));
+    goto end;
+  }
   
   /******** PART I: fill pconn and pplayer ********/
 
@@ -2889,7 +2901,31 @@
     pconn = caller;
   }
 
-  /******** PART II: do the attaching ********/
+  if (check) {
+    goto end;
+  }
+
+  return take_player_for_conn(caller, pplayer, pconn);
+
+  end:;
+  /* free our args */
+  for (i = 0; i < ntokens; i++) {
+    free(arg[i]);
+  }
+  return res;
+
+}
+
+/**************************************************************************
+  Take over a player. If a connection already has control of that player,
+  disallow it.
+**************************************************************************/
+bool take_player_for_conn(struct connection *caller, struct player *pplayer,
+                          struct connection *pconn) 
+{
+  char msg[MAX_LEN_MSG];
+  bool is_newgame = server_state == PRE_GAME_STATE && game.info.is_new_game;
+  bool res = FALSE;
 
   /* check allowtake for permission */
   if (!is_allowed_to_take(pplayer, FALSE, msg)) {
@@ -2899,15 +2935,14 @@
 
   /* taking your own player makes no sense. */
   if (pconn->player == pplayer && !pconn->observer) {
-    cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s already controls %s"),
-              pconn->username, pplayer->name);
+    if (!game.info.hotseat) {
+      cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s already controls %s"),
+                pconn->username, pplayer->name);
+    }
     goto end;
   } 
 
   res = TRUE;
-  if (check) {
-    goto end;
-  }
 
   /* if we want to switch players, reset the client if the game is running */
   if (server_state == RUN_GAME_STATE) {
@@ -2991,10 +3026,6 @@
             _("AI") : _("Human"), pplayer->is_alive ? _("Alive") : _("Dead"));
 
   end:;
-  /* free our args */
-  for (i = 0; i < ntokens; i++) {
-    free(arg[i]);
-  }
   return res;
 }
 
@@ -3269,7 +3300,11 @@
     }
     players_iterate(pplayer) {
       if (strcmp(pconn->username, pplayer->username) == 0) {
-        attach_connection_to_player(pconn, pplayer);
+        if (game.info.hotseat) {
+          attach_connection_to_player(pconn, get_player(game.info.phase));
+        } else {
+          attach_connection_to_player(pconn, pplayer);
+        }
         break;
       }
     } players_iterate_end;
diff -ruN -Xfreeciv/diff_ignore freeciv/server/stdinhand.h 
freeciv-hotseat/server/stdinhand.h
--- freeciv/server/stdinhand.h  2005-10-15 21:13:03.000000000 +0200
+++ freeciv-hotseat/server/stdinhand.h  2005-11-04 18:39:22.000000000 +0100
@@ -33,7 +33,8 @@
 void show_players(struct connection *caller);
 
 bool load_command(struct connection *caller, char *arg, bool check);
-
+bool take_player_for_conn(struct connection *caller,
+                          struct player *pplayer, struct connection *pconn);
 
 void toggle_ai_player_direct(struct connection *caller,
                             struct player *pplayer);

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